[
  {
    "path": ".idea/vcs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping directory=\"\" vcs=\"Git\" />\n  </component>\n</project>"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright {yyyy} {name of copyright owner}\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n"
  },
  {
    "path": "README.md",
    "content": "# Groovy In Action\nSource code of the book [Groovy in Action, 2nd edition (manning,](http://manning.com/koenig2/?a_aid=regina&a_bid=8ade3b0e)\n[amazon)](http://www.amazon.com/gp/product/1935182447/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=1935182447&linkCode=as2&tag=httpgroovycan-20&linkId=XLTAIALXLIUBWPOH)\n\n### Use it? Star it!\nAll source code is free for everybody's use under the Apache 2 license.\n\nIf you want to do us a favor in return, please give this repo a \"star\" such that we can get at least a feeling of how many developers are using it. _Thanks!_ \n\n# Prerequisites\n\n* Java 1.7 or higher\n* Groovy 2.4.1 or higher\n\n# Considerations\n\nOne can run all listings by calling\n\n    groovy alltests\n\nHowever, since some listings rely on external\nconstraints like special versions of the JVM\n(e.g. to test Groovy features for Java 8) or\nOS-specific integration features, some listings\nmay be excluded from execution.\n\nListings are usually made such that you can \n`cd` into the directory for that chapter and\ncall the listing via\n\n\tgroovy mylistingname\n\t\nIf no other instructions apply, you best \nuse Groovy 2.4.1 and Java 7. More recent versions\nwill also work in most cases.\n\nThere are code adaptions to Java 8. \nPlease use the Java_8 branch if you rely on those.\n\nKeep groovin'\n\nThe authors\t\n"
  },
  {
    "path": "alltests.groovy",
    "content": "for (number in 1..20) {\n    def ant = new AntBuilder()\n    def dir = 'listings/chap' + number.toString().padLeft(2, '0')\n\n    def runner = \"../../test\"\n    if (number == 11) {\n        def home = System.getenv(\"JAVA_HOME\")\n        jfxcp = \"$home/jre/lib/jfxrt.jar\"\n        runner = \"-classpath $jfxcp \" + runner\n    } else if (number == 10) {\n      // add type extension source files to classpath\n      runner = \"-classpath . \" + runner\n    }\n\n    println \"testing dir $dir\"\n    def os = System.getProperty(\"os.name\").toLowerCase()\n    def groovy = os.contains('windows') ? System.getenv(\"GROOVY_HOME\") + '\\\\bin\\\\groovy.bat' : 'groovy'\n    ant.exec(\n            dir: dir,\n            outputproperty: \"cmdOut\",\n            executable: groovy) {\n        arg(line: runner)\n    }\n    def out = ant.project.properties.cmdOut\n    println out\n    if (out.contains('FAILED')) {\n        out.split(\"\\n\").grep(~/.*FAILED:.*/).each { println it }\n        System.exit(1)\n    }\n}"
  },
  {
    "path": "listings/allsources.txt",
    "content": "./appD/Listing_D_01_GStrings.groovy\n./appD/Listing_D_02_Lists.groovy\n./appD/Listing_D_03_Closures.groovy\n./appD/Listing_D_04_Regex.groovy\n./appD/Listing_D_05_GPath.groovy\n./chap01/customers.xml\n./chap01/data.txt\n./chap01/groovysh.txt\n./chap01/Listing_01_01_Gold.groovy\n./chap01/snippet0101_customers.groovy\n./chap01/snippet0101_fileLineNumbers.groovy\n./chap01/snippet0101_newDates.txt\n./chap01/snippet0101_printPackageNames.groovy\n./chap01/snippet0101_printPackageNamesGpath.groovy\n./chap01/snippet0102_printGroovyWebSiteCount.groovy\n./chap01/snippet0103_googleIpAdr.groovy\n./chap02/Book.groovy\n./chap02/Listing_02_01_Assertions.groovy\n./chap02/Listing_02_02_Book.txt\n./chap02/Listing_02_03_BookScript.groovy\n./chap02/Listing_02_04_BookBean.groovy\n./chap02/Listing_02_05_ImmutableBook.groovy\n./chap02/Listing_02_06_Grab.groovy\n./chap02/Listing_02_07_Clinks.groovy\n./chap02/Listing_02_08_ControlStructures.groovy\n./chap02/snippet0201_comments.groovy\n./chap02/snippet0202_failing_assert.groovy\n./chap02/snippet0202_failing_assertion_error.txt\n./chap02/snippet0203_clinks_java.groovy\n./chap02/snippet0203_gstring.groovy\n./chap02/snippet0203_int_usage.groovy\n./chap02/snippet0203_map_usage.groovy\n./chap02/snippet0203_range_usage.groovy\n./chap02/snippet0203_roman.groovy\n./chap02/snippet0204_evaluate_jdk7_only.groovy\n./chap02/snippet0204_evaluate_jdk8_only.groovy\n./chap02/snippet0204_failing_typechecked.groovy\n./chap03/ArrayListSummer.java\n./chap03/extra_escaped_characters_table36.groovy\n./chap03/extra_method_operators_table34.groovy\n./chap03/extra_numeric_literals_table32.groovy\n./chap03/extra_numerical_coercion_table310.groovy\n./chap03/extra_optional_typing_table33.groovy\n./chap03/extra_primitive_values_table31.groovy\n./chap03/Listing_03_01_PrimitiveMethodsObjectOperators.groovy\n./chap03/Listing_03_02_ListMapCast.groovy\n./chap03/Listing_03_03_DefiningOperators.groovy\n./chap03/Listing_03_04_DefiningGStrings.groovy\n./chap03/Listing_03_05_StringOperations.groovy\n./chap03/Listing_03_06_RegexGStrings.groovy\n./chap03/Listing_03_07_RegularExpressions.groovy\n./chap03/Listing_03_08_EachMatch.groovy\n./chap03/Listing_03_09_PatternReuse.groovy\n./chap03/Listing_03_10_PatternsClassification.groovy\n./chap03/Listing_03_11_NumberMethodsGDK.groovy\n./chap03/regex_dgm.txt\n./chap03/snippet0301_autoboxing.groovy\n./chap03/snippet0304_GString_internals.groovy\n./chap03/snippet0304_stringbuffer.groovy\n./chap03/snippet0305_matcher_each_group.groovy\n./chap03/snippet0305_matcher_groups.groovy\n./chap03/snippet0305_matcher_parallel_assignment.groovy\n./chap03/snippet0305_matcher_plain.groovy\n./chap03/snippet0306_GDK_methods_for_numbers.groovy\n./chap04/extra_EnumRange.groovy\n./chap04/extra_ListCast.groovy\n./chap04/extra_ListTable.groovy\n./chap04/extra_Map_as.groovy\n./chap04/extra_Map_group.groovy\n./chap04/extra_MaxMinSum.groovy\n./chap04/extra_SplitList.groovy\n./chap04/Listing_04_01_range_declarations.groovy\n./chap04/Listing_04_02_ranges_are_objects.groovy\n./chap04/Listing_04_03_custom_ranges.groovy\n./chap04/Listing_04_04_list_declarations.groovy\n./chap04/Listing_04_05_list_subscript_operator.groovy\n./chap04/Listing_04_06_list_add_remove.groovy\n./chap04/Listing_04_07_lists_control_structures.groovy\n./chap04/Listing_04_08_list_content_manipulation.groovy\n./chap04/Listing_04_09_list_other_methods.groovy\n./chap04/Listing_04_10_list_quicksort.groovy\n./chap04/Listing_04_11_list_mapreduce.groovy\n./chap04/Listing_04_12_map_declarations.groovy\n./chap04/Listing_04_13_map_accessors.groovy\n./chap04/Listing_04_14_map_query_methods.groovy\n./chap04/Listing_04_15_map_iteration.groovy\n./chap04/Listing_04_16_map_content.groovy\n./chap04/Listing_04_17_map_example.groovy\n./chap04/snippet0402_ListAsSet.groovy\n./chap04/snippet0402_ListRemoveNulls.groovy\n./chap04/snippet0402_ListStreams_jdk8_plus.groovy\n./chap04/snippet0403_Map_Ctor_Expression.groovy\n./chap04/snippet0403_Map_Ctor_Unquoted.groovy\n./chap04/snippet0403_Map_MapReduce.groovy\n./chap04/snippet0403_Map_String_accessors.groovy\n./chap05/extra_Closure_delegate.groovy\n./chap05/extra_Closure_myWith.groovy\n./chap05/extra_ClosureProperty.groovy\n./chap05/Listing_05_01_closure_simple_declaration.groovy\n./chap05/Listing_05_02_simple_method_closure.groovy\n./chap05/Listing_05_03_multi_method_closure.groovy\n./chap05/Listing_05_04_closure_all_declarations.groovy\n./chap05/Listing_05_05_simple_closure_calling.groovy\n./chap05/Listing_05_06_calling_closures.groovy\n./chap05/Listing_05_07_simple_currying.groovy\n./chap05/Listing_05_08_logging_curry_example.groovy\n./chap05/Listing_05_09_closure_scope.groovy\n./chap05/Listing_05_10_closure_accumulator.groovy\n./chap05/Listing_05_11_visitor_pattern.groovy\n./chap05/snippet0501_envelope.groovy.txt\n./chap05/snippet0504_closure_default_params.groovy\n./chap05/snippet0504_closure_isCase.groovy\n./chap05/snippet0504_closure_paramcount.groovy\n./chap05/snippet0505_map_with.groovy\n./chap05/snippet0505_scoping.groovy\n./chap05/snippet0506_closure_return.groovy\n./chap05/snippet0507_closure_composition.groovy\n./chap05/snippet0508_memoize.groovy\n./chap05/snippet0509_trampoline.groovy\n./chap06/extra_if_return.groovy\n./chap06/extra_in_operator.groovy\n./chap06/extra_switch_return.groovy\n./chap06/Listing_06_01_groovy_truth.groovy\n./chap06/Listing_06_02_assignment_bug.groovy\n./chap06/Listing_06_03_if_then_else.groovy\n./chap06/Listing_06_04_conditional_operator.groovy\n./chap06/Listing_06_05_switch_basic.groovy\n./chap06/Listing_06_06_switch_advanced.groovy\n./chap06/Listing_06_07_assert_host.groovy\n./chap06/Listing_06_08_while.groovy\n./chap06/Listing_06_09_for.groovy\n./chap06/Listing_06_10_break_continue.groovy\n./chap06/Listing_06_11_exception_example.groovy\n./chap06/myFileName.txt\n./chap06/snippet0602_bad_file_read.groovy\n./chap06/snippet0602_bad_file_read_with_message.groovy\n./chap06/snippet0602_failing_assert.groovy\n./chap06/snippet0603_each_loop_iterate.groovy\n./chap06/snippet0603_file_iterate_lines.groovy\n./chap06/snippet0603_for_loop_iterate.groovy\n./chap06/snippet0603_null_iterate.groovy\n./chap06/snippet0603_object_iterate.groovy\n./chap06/snippet0603_regex_iterate_match.groovy\n./chap06/snippet0604_multicatch.groovy\n./chap07/business/Vendor.groovy\n./chap07/Listing_07_01_Declaring_Variables.groovy\n./chap07/Listing_07_02_TypeBreaking_Assignment.groovy\n./chap07/Listing_07_03_Referencing_Fields.groovy\n./chap07/Listing_07_04_Overriding_Field_Access.groovy\n./chap07/Listing_07_05_Declaring_Methods.groovy\n./chap07/Listing_07_06_Declaring_Parameters.groovy\n./chap07/Listing_07_07_Parameter_Usages.groovy\n./chap07/Listing_07_08_Safe_Dereferencing.groovy\n./chap07/Listing_07_09_Instantiation.groovy\n./chap07/Listing_07_10_Instantiation_Named.groovy\n./chap07/Listing_07_11_Classes.groovy\n./chap07/Listing_07_13_Import.groovy\n./chap07/Listing_07_14_Import_As_BugFix.groovy\n./chap07/Listing_07_15_Import_As_NameClash.groovy\n./chap07/Listing_07_16_Multimethods.groovy\n./chap07/Listing_07_17_MultiEquals.groovy\n./chap07/Listing_07_18_Traits.groovy\n./chap07/Listing_07_19_Declaring_Beans.groovy\n./chap07/Listing_07_20_Calling_Beans.groovy\n./chap07/Listing_07_21_Calling_Beans_Advanced.groovy\n./chap07/Listing_07_22_Property_Methods.groovy\n./chap07/Listing_07_23_Expando.groovy\n./chap07/Listing_07_24_GPath.groovy\n./chap07/snippet0703_Implicit_Closure_To_SAM.groovy\n./chap07/snippet0705_Spread_List.groovy\n./chap07/snippet0705_Spread_Map.groovy\n./chap07/snippet0705_Spread_Range.groovy\n./chap07/thirdparty/MathLib.groovy\n./chap07/thirdparty2/MathLib.groovy\n./chap08/custom/Custom.groovy\n./chap08/custom/useCustom.groovy\n./chap08/failing_Listing_08_15_EMC_static.groovy\n./chap08/failing_Listing_08_16_EMC_super.groovy\n./chap08/groovy/runtime/metaclass/custom/CustomMetaClass.groovy\n./chap08/Listing_08_01_method_missing.groovy\n./chap08/Listing_08_02_mini_gorm.groovy\n./chap08/Listing_08_03_property_missing.groovy\n./chap08/Listing_08_04_bin_property.groovy\n./chap08/Listing_08_05_closure_dynamic.groovy\n./chap08/Listing_08_06_property_method.groovy\n./chap08/Listing_08_07_MetaClass_jdk7_only.groovy\n./chap08/Listing_08_07_MetaClass_jdk8_plus.groovy\n./chap08/Listing_08_08_ProxyMetaClass.groovy\n./chap08/Listing_08_09_Expando.groovy\n./chap08/Listing_08_10_EMC.groovy\n./chap08/Listing_08_11_EMC_Groovy_Class.groovy\n./chap08/Listing_08_12_EMC_Groovy_Object.groovy\n./chap08/Listing_08_13_EMC_Java_Object.groovy\n./chap08/Listing_08_14_EMC_Builder.groovy\n./chap08/Listing_08_15_EMC_static.groovy\n./chap08/Listing_08_16_EMC_super.groovy\n./chap08/Listing_08_17_EMC_hooks.groovy\n./chap08/Listing_08_18_Existing_Categories.groovy\n./chap08/Listing_08_19_Marshal.groovy\n./chap08/Listing_08_20_MarshalCategory.groovy\n./chap08/Listing_08_21_Test_Mixin.groovy\n./chap08/Listing_08_22_Sieve_Mixin.groovy\n./chap08/Listing_08_23_Millimeter.groovy\n./chap08/Listing_08_24_create_factory.groovy\n./chap08/Listing_08_25_fake_assign.groovy\n./chap08/Listing_08_26_restore_emc.groovy\n./chap08/Listing_08_27_intercept_cache_invoke.groovy\n./chap08/markup.html\n./chap09/gradlew.bat\n./chap09/Listing_09_01_ToStringDetective.groovy\n./chap09/Listing_09_02_ToStringSleuth.groovy\n./chap09/Listing_09_03_EqualsAndHashCode.groovy\n./chap09/Listing_09_04_TupleConstructor.groovy\n./chap09/Listing_09_05_Lazy.groovy\n./chap09/Listing_09_06_IndexedProperty.groovy\n./chap09/Listing_09_07_InheritConstructors.groovy\n./chap09/Listing_09_08_Sortable.groovy\n./chap09/Listing_09_09_Builder.groovy\n./chap09/Listing_09_10_Canonical.groovy\n./chap09/Listing_09_11_Immutable.groovy\n./chap09/Listing_09_12_Delegate.groovy\n./chap09/Listing_09_13_Singleton.groovy\n./chap09/Listing_09_14_Memoized.groovy\n./chap09/Listing_09_15_TailRecursive.groovy\n./chap09/Listing_09_16_Log.groovy\n./chap09/Listing_09_17_Synchronized.groovy\n./chap09/Listing_09_18_SynchronizedCustomLock.groovy\n./chap09/Listing_09_19_ReadWriteLock.groovy\n./chap09/Listing_09_20_AutoClone.groovy\n./chap09/Listing_09_21_AutoCloneCopyConstructor.groovy\n./chap09/Listing_09_22_AutoExternalize.groovy\n./chap09/Listing_09_23_TimedInterrupt.groovy\n./chap09/Listing_09_24_ThreadInterrupt.groovy\n./chap09/Listing_09_25_ConditionalInterrupt.groovy\n./chap09/Listing_09_26_Field.groovy\n./chap09/Listing_09_27_BaseScript.groovy\n./chap09/Listing_09_28_AstByHand.groovy\n./chap09/Listing_09_29_AstByHandWithUtils.groovy\n./chap09/Listing_09_30_AstBuildFromSpec.groovy\n./chap09/Listing_09_31_AstBuildFromString.groovy\n./chap09/Listing_09_32_AstBuildFromStringMixed.groovy\n./chap09/Listing_09_33_AstBuildFromCode.groovy\n./chap09/Listing_09_34_GreeterMainTransform.groovy\n./chap09/Listing_09_35_GreeterMainTransform2.groovy\n./chap09/Listing_09_38_AstTesting1.groovy\n./chap09/Listing_09_39_AstTesting2.groovy\n./chap09/Listing_09_40_AstTesting3.groovy\n./chap09/Listing_09_41_AstTesting4.groovy\n./chap09/Listing_09_42_AstTesting5.groovy\n./chap09/Listings.txt\n./chap09/settings.gradle\n./chap09/snippet0902_autoCloneDefault.txt\n./chap09/snippet0902_autoCloneSerialization.txt\n./chap09/snippet0902_autoExternalize.txt\n./chap09/snippet0902_fieldEquivalent.txt\n./chap09/snippet0902_mapCreation.txt\n./chap09/snippet0902_noisySetDelegateByHand.txt\n./chap09/snippet0902_noisySetInheritance.txt\n./chap09/snippet0902_nonTailCallReverseList.txt\n./chap09/snippet0902_readWriteByHand.txt\n./chap09/snippet0902_readWriteLock.txt\n./chap09/snippet0902_singletonByHand.txt\n./chap09/snippet0902_toStringEquivalent.txt\n./chap09/snippet0903_greeterExpanded.txt\n./chap09/snippet0903_greeterScript.txt\n./chap09/snippet0903_localMain.txt\n./chap09/snippet0903_localMainTransformation.txt\n./chap09/snippet0905_GetCompiledTimeScript.txt\n./chap09/src/main/groovy/regina/CompiledAtASTTransformation.groovy\n./chap09/src/test/groovy/regina/CompiledAtASTTransformationTest.groovy\n./chap10/extra1004_JavaDispatch.java\n./chap10/extra1004_RuntimeGroovyDispatch.groovy\n./chap10/Greeter.java\n./chap10/Listing_10_01_Duck.groovy\n./chap10/Listing_10_02_failing_Typo.groovy\n./chap10/Listing_10_03_ClassTC.groovy\n./chap10/Listing_10_04_OneMethodTC.groovy\n./chap10/Listing_10_05_CompileTimeTypo.groovy\n./chap10/Listing_10_06_MethodNameTypo.groovy\n./chap10/Listing_10_07_MethodArgsFlipped.groovy\n./chap10/Listing_10_08_InvalidAssignments.groovy\n./chap10/Listing_10_09_AssignmentsWithCoercion.groovy\n./chap10/Listing_10_10_DefField.groovy\n./chap10/Listing_10_11_InPlaceList.groovy\n./chap10/Listing_10_12_Generics.groovy\n./chap10/Listing_10_13_ListStyleCtorRuntime.groovy\n./chap10/Listing_10_14_ListStyleCtorTC.groovy\n./chap10/Listing_10_15_MapStyleCtorBad.groovy\n./chap10/Listing_10_16_ListStyleCtor.groovy\n./chap10/Listing_10_17_ListStyleCtorFixed.groovy\n./chap10/Listing_10_18_CodeAsData.groovy\n./chap10/Listing_10_19_ClosuresBadReturnType.groovy\n./chap10/Listing_10_20_UserValidation.groovy\n./chap10/Listing_10_21_UserValidationTC.groovy\n./chap10/Listing_10_22_UserValidation_ExplicitTypes.groovy\n./chap10/Listing_10_23_UserValidation_SAM.groovy\n./chap10/Listing_10_24_UserValidation_ClosureParams.groovy\n./chap10/Listing_10_25_UserValidation_DSL.groovy\n./chap10/Listing_10_26_UserValidation_DelegatesTo.groovy\n./chap10/Listing_10_27_UserValidation_DelegatesToTarget.groovy\n./chap10/Listing_10_28_Category.groovy\n./chap10/Listing_10_29_EMC.groovy\n./chap10/Listing_10_30_Builder.groovy\n./chap10/Listing_10_31_MixedTypeChecking.groovy\n./chap10/Listing_10_32_Skip.groovy\n./chap10/Listing_10_33_FlowTyping.groovy\n./chap10/Listing_10_34_FlowTypingOk.groovy\n./chap10/Listing_10_35_LUB.groovy\n./chap10/Listing_10_36_Condition.groovy\n./chap10/Listing_10_37_ClosureSharedVar.groovy\n./chap10/Listing_10_38_LubError.groovy\n./chap10/Listing_10_39_LubOk.groovy\n./chap10/Listing_10_41_FibBench.groovy\n./chap10/Listing_10_41_JavaGreeter.txt\n./chap10/Listing_10_42_StaticCompileDispatch.groovy\n./chap10/Listing_10_43_MonkeyPatching.groovy\n./chap10/Listing_10_44_BookingDSL.groovy\n./chap10/Listing_10_45_MultiValidation.groovy\n./chap10/Listing_10_46_RobotExtension.groovy\n./chap10/Listing_10_47_SQLExtension.groovy\n./chap10/markup.html\n./chap10/snippet1003_GroovyGreeter.groovy\n./chap10/snippet1005_RobotMainTC.groovy\n./chap10/snippet1005_SqlMainTC.groovy\n./chap10/User.groovy\n./chap11/Listing_11_01_SquaresFactors.xml\n./chap11/Listing_11_02_SquaresFactors.java\n./chap11/Listing_11_03_MarkupBuilderPlain.groovy\n./chap11/Listing_11_04_NodeBuilder.groovy\n./chap11/Listing_11_05_NodeBuilderLogic.groovy\n./chap11/Listing_11_06_MarkupBuilderLogic.groovy\n./chap11/Listing_11_07_MarkupBuilderHtml.groovy\n./chap11/Listing_11_08_StreamingMarkupBuilderLogic.groovy\n./chap11/Listing_11_09_ExampleBuild.xml\n./chap11/Listing_11_10_PW_SwingBuilder.groovy\n./chap11/Listing_11_11_Swing_Widgets.groovy\n./chap11/Listing_11_12_Swing_Layout.groovy\n./chap11/Listing_11_13_Table_Demo.groovy\n./chap11/Listing_11_14_Binding.groovy\n./chap11/Listing_11_15_Plotter.groovy\n./chap11/Listing_11_16_Groovyfx.groovy\n./chap11/Listing_11_17_CalorieCounterBuilderSupport.groovy\n./chap11/Listing_11_18_CalorieCounterFactoryBuilderSupport.groovy\n./chap11/Listing_11_19_CalorieCounterByHand.groovy\n./chap11/markup.html\n./chap11/snippet1103_MarkupBuilderOutput.html\n./chap11/snippet1103_MarkupWithHyphen.groovy\n./chap11/snippet1106_AntBuilderIf.groovy\n./chap11/snippet1106_AntIf.xml\n./chap11/snippet1107_binding.txt\n./chap11/snippet1107_Printer.groovy\n./chap12/data/example.txt\n./chap12/Listing_12_01_info_jdk6_only.groovy\n./chap12/Listing_12_01_info_jdk7_only.groovy\n./chap12/Listing_12_01_info_jdk8_plus.groovy\n./chap12/Listing_12_02_properties.groovy\n./chap12/Listing_12_03_File_Iteration.groovy\n./chap12/Listing_12_04_Filesystem.groovy\n./chap12/Listing_12_05_Traversal.groovy\n./chap12/Listing_12_06_File_Read.groovy\n./chap12/Listing_12_07_File_Write.groovy\n./chap12/Listing_12_08_Writer_LeftShift.groovy\n./chap12/Listing_12_09_File_Transform_jdk7_plus.groovy\n./chap12/Listing_12_10_File_ObjectStreams.groovy\n./chap12/Listing_12_11_Temp_Dir.groovy\n./chap12/Listing_12_12_Threads.groovy\n./chap12/Listing_12_13_Processes_UnixCommands.groovy\n./chap12/Listing_12_14_Processes_ZipUnzip.groovy\n./chap12/Listing_12_15_SimpleTemplateEngine.groovy\n./chap12/Listing_12_16_GroovletExample.groovy\n./chap12/Listing_12_17_HelloWorldGroovlet.groovy\n./chap12/Listing_12_19_InspectGroovlet.groovy\n./chap12/Listing_12_20_HiLowGame.groovy\n./chap12/Listing_12_21_NumberTemplate.txt\n./chap12/Listing_12_22_TemplateGroovlet.groovy\n./chap12/Number.template.html\n./chap12/snippet1201_SlowTyping.groovy\n./chap12/snippet1201_UseCategory.groovy\n./chap12/snippet1202_base64.groovy\n./chap12/web.xml\n./chap13/extra_NeoGremlinGraph.groovy\n./chap13/layering/AthleteApplication.groovy\n./chap13/layering/AthleteDAO.groovy\n./chap13/layering/DataAccessObject.groovy\n./chap13/layering/DbHelper.groovy\n./chap13/Listing_13_01_Connecting.groovy\n./chap13/Listing_13_02_ConnectingDataSource.groovy\n./chap13/Listing_13_03_Creating.groovy\n./chap13/Listing_13_04_Inserting.groovy\n./chap13/Listing_13_05_Reading.groovy\n./chap13/Listing_13_06_Updating.groovy\n./chap13/Listing_13_07_Delete.groovy\n./chap13/Listing_13_08_Transactions.groovy\n./chap13/Listing_13_09_Batching.groovy\n./chap13/Listing_13_10_Paging.groovy\n./chap13/Listing_13_11_Metadata.groovy\n./chap13/Listing_13_12_MoreMetadata.groovy\n./chap13/Listing_13_13_NamedOrdinal.groovy\n./chap13/Listing_13_14_StoredProcBasic.groovy\n./chap13/Listing_13_15_StoredProcParam.groovy\n./chap13/Listing_13_16_StoredProcInOut.groovy\n./chap13/Listing_13_17_DataSetBasics.groovy\n./chap13/Listing_13_18_DataSetFiltering.groovy\n./chap13/Listing_13_19_DataSetViews.groovy\n./chap13/Listing_13_20_DbHelper.txt\n./chap13/Listing_13_21_DataAccessObject.txt\n./chap13/Listing_13_22_AthleteDAO.txt\n./chap13/Listing_13_23_AthleteApplication.txt\n./chap13/Listing_13_24_AthleteAppMain.groovy\n./chap13/Listing_13_25_AthleteAppTest.groovy\n./chap13/Listing_13_26_MongoAthletes.groovy\n./chap13/Listing_13_27_NeoAthletes.groovy\n./chap13/Listing_13_28_NeoGremlin.groovy\n./chap13/snippet1301_ConnectingWithGrab.groovy\n./chap13/snippet1301_ConnectingWithInstance.groovy\n./chap13/snippet1301_ConnectingWithMap.groovy\n./chap13/snippet1301_ReadEachRow.groovy\n./chap13/snippet1301_ReadEachRowList.groovy\n./chap13/snippet1301_ReadQuery.groovy\n./chap13/snippet1301_ReadRows.groovy\n./chap13/util/DbUtil.groovy\n./chap13/util/MarathonRelationships.groovy\n./chap13/util/Neo4jUtil.groovy\n./chap14/data/GroovyPlans.html\n./chap14/data/GroovyPlans.template.html\n./chap14/data/plan.json\n./chap14/data/plan.xml\n./chap14/data/StreamedGroovyPlans.html\n./chap14/data/style.css\n./chap14/data/XPathGroovyPlans.html\n./chap14/Listing_14_01_Plan.txt\n./chap14/Listing_14_02_DOM.groovy\n./chap14/Listing_14_03_DOM_Category.groovy\n./chap14/Listing_14_04_XmlParser.groovy\n./chap14/Listing_14_05_XmlSlurper.groovy\n./chap14/Listing_14_06_SAX.groovy\n./chap14/Listing_14_07_StAX.groovy\n./chap14/Listing_14_08_XmlBoiler.groovy\n./chap14/Listing_14_09_XmlStreamer.groovy\n./chap14/Listing_14_10_StreamedHtml.groovy\n./chap14/Listing_14_11_UpdateDomCategory.groovy\n./chap14/Listing_14_12_UpdateParser.groovy\n./chap14/Listing_14_13_UpdateSlurper.groovy\n./chap14/Listing_14_14_XPath.groovy\n./chap14/Listing_14_15_GroovyPlansTemplate.txt\n./chap14/Listing_14_16_XPathTemplate.groovy\n./chap14/Listing_14_17_JsonParser.groovy\n./chap14/Listing_14_18_JsonBuilder.groovy\n./chap14/Listing_14_19_JsonBuilderLogic.groovy\n./chap14/Listing_14_20_JsonOutputAthlete.groovy\n./chap14/log4j.xml\n./chap14/UpdateChecker.groovy\n./chap15/data/conv.templ.xml\n./chap15/Listing_15_01_RSS_bbcnews.groovy\n./chap15/Listing_15_02_ATOM_devworks.groovy\n./chap15/Listing_15_03_REST_jira_url.groovy\n./chap15/Listing_15_04_REST_jira_httpb_get.groovy\n./chap15/Listing_15_05_REST_currency_httpb_get.groovy\n./chap15/Listing_15_06_REST_currency_httpb_post.groovy\n./chap15/Listing_15_07_REST_currency_jaxrs.groovy\n./chap15/Listing_15_08_REST_currency_jaxrs_proxy.groovy\n./chap15/Listing_15_09_XMLRPC_echo.groovy\n./chap15/Listing_15_10_XMLRPC_jira.groovy\n./chap15/Listing_15_11_SOAP_wsdl.groovy\n./chap15/Listing_15_12_SOAP11_currency_url.groovy\n./chap15/Listing_15_13_SOAP12_currency_httpb.groovy\n./chap15/Listing_15_14_SOAP11_currency_wslite.groovy\n./chap15/Listing_15_15_SOAP12_currency_wslite.groovy\n./chap16/HelloIntegrationWorld.java\n./chap16/Listing_16_01_HelloIntegration.groovy\n./chap16/Listing_16_02_HelloIntegrationJava.txt\n./chap16/Listing_16_03_MultilineScript.groovy\n./chap16/Listing_16_04_UsingEval.groovy\n./chap16/Listing_16_05_Binding.groovy\n./chap16/Listing_16_06_BindingTwoWay.groovy\n./chap16/Listing_16_07_ClassInScript.groovy\n./chap16/Listing_16_08_Payment_calculator.groovy\n./chap16/Listing_16_09_MethodsInBinding.groovy\n./chap16/Listing_16_10_ShapeInfoMain.txt\n./chap16/Listing_16_11_SpringConfig.txt\n./chap16/Listing_16_12_BeanToString.groovy\n./chap16/shapes/Circle.groovy\n./chap16/shapes/MaxAreaInfo.groovy\n./chap16/shapes/MaxPerimeterInfo.java\n./chap16/shapes/Shape.java\n./chap16/shapes/ShapeInfo.java\n./chap16/shapes/ShapeInfoMain.java\n./chap16/shapes/Square.java\n./chap16/spring/common/Shape.java\n./chap16/spring/common/ShapeInfo.java\n./chap16/spring/groovy/Circle.groovy\n./chap16/spring/groovy/MaxAreaInfo.groovy\n./chap16/spring/java/MaxPerimeterInfo.java\n./chap16/spring/java/ShapeInfoFactoryMain.java\n./chap16/spring/java/ShapeInfoMain.java\n./chap16/spring/java/ShapeInfoSpringMain.java\n./chap16/spring/java/Square.java\n./chap16/spring/resources/beans.xml\n./chap17/automation/src/main/groovy/Calculator.groovy\n./chap17/automation/src/test/groovy/CalculatorTest.groovy\n./chap17/cobertura/src/main/groovy/BiggestPairCalc.groovy\n./chap17/cobertura/src/main/groovy/BiggestPairCalcFixed.groovy\n./chap17/cobertura/src/test/groovy/BiggestPairCalcTest.groovy\n./chap17/Converter.groovy\n./chap17/Counter.groovy\n./chap17/extra_ParameterizedTestNG.groovy\n./chap17/extra_TestNG.groovy\n./chap17/Farm.groovy\n./chap17/Listing_17_01_Celsius.groovy\n./chap17/Listing_17_02_CounterTest.groovy\n./chap17/Listing_17_03_HashMapTest.groovy\n./chap17/Listing_17_04_GroovyTestSuite.groovy\n./chap17/Listing_17_05_AllTestSuite.groovy\n./chap17/Listing_17_06_DataDrivenJUnitTest.groovy\n./chap17/Listing_17_07_PropertyBased.groovy\n./chap17/Listing_17_08_Balancer.groovy\n./chap17/Listing_17_09_BalancerStub.groovy\n./chap17/Listing_17_10_BalancerMock.groovy\n./chap17/Listing_17_11_LoggingCounterTest.groovy\n./chap17/Listing_17_12_JUnitPerf.groovy\n./chap17/Listing_17_13_SpockSimple.groovy\n./chap17/Listing_17_14_SpockMock.groovy\n./chap17/Listing_17_15_SpockMockWildcards.groovy\n./chap17/Listing_17_16_SpockMockClosureChecks.groovy\n./chap17/Listing_17_17_SpockDataDriven.groovy\n./chap17/LoggingCounter.groovy\n./chap17/MovieTheater.groovy\n./chap17/Purchase.groovy\n./chap17/snippet1701_JUnit4.groovy\n./chap17/snippet1704_listPropertyCheck.groovy\n./chap18/Listing_18_01_ConcurrentSquares.groovy\n./chap18/Listing_18_02_ConcurrentSquaresTransparent.groovy\n./chap18/Listing_18_03_ConcurrentSquaresTransitive.groovy\n./chap18/Listing_18_04_MapFilterReduce.groovy\n./chap18/Listing_18_05_SquaresMapReduce.groovy\n./chap18/Listing_18_06_Dataflow.groovy\n./chap18/Listing_18_07_DataflowStreams.groovy\n./chap18/Listing_18_08_Actors.groovy\n./chap18/Listing_18_09_ActorsLifecycle.groovy\n./chap18/Listing_18_10_ActorsMessageAware.groovy\n./chap18/Listing_18_11_Agent.groovy\n./chap18/Listing_18_12.txt\n./chap18/Listing_18_13_YahooForkJoin.groovy\n./chap18/Listing_18_14_YahooMapReduce.groovy\n./chap18/Listing_18_15_YahooDataflow.groovy\n./chap18/snippet1801_startThread.groovy\n./chap18/snippet1803_java_parallel_streams_jdk8_only.groovy\n./chap18/snippet1804_deadlock.groovy\n./chap18/snippet1804_nondeterministic.groovy\n./chap18/YahooService.groovy\n./chap19/extra_19_41_FetchOptions.groovy\n./chap19/FetchOptions.groovy\n./chap19/FetchOptionsBuilder.groovy\n./chap19/Listing_19_06_Binding.groovy\n./chap19/Listing_19_29_OrderDSL.groovy\n./chap19/Listing_19_30_WhenIfControlStructure.groovy\n./chap19/Listing_19_31_Until_failing_.groovy\n./chap19/Listing_19_32_UntilControlStructure.groovy\n./chap19/Listing_19_38_GivenWhenThen.groovy\n./chap19/Listing_19_42_FetchOptionsScript.groovy\n./chap19/Listing_19_43_RubyStyleNewify.groovy\n./chap19/Listing_19_44_PythonStyleNewify.groovy\n./chap19/Listing_19_45_Terms.groovy\n./chap19/Listing_19_46_NewifyInjected.txt\n./chap19/Listing_19_47_No_IO.groovy\n./chap19/Listing_19_48_ArithmeticShell.groovy\n./chap19/Listing_19_49_TimedInterrupt.groovy\n./chap19/Listing_19_50_SystemExitGuard.groovy\n./chap19/Listing_19_52_QueryCustomizer.groovy\n./chap19/Listings.txt\n./chap19/Query.groovy\n./chap19/v01/Listing_19_01_SelfContainedScript.groovy\n./chap19/v02/integration/CaseRobotBaseScript.groovy\n./chap19/v02/integration/CustomBinding.groovy\n./chap19/v02/integration/RobotBaseScript.groovy\n./chap19/v02/Listing_19_04_MainSimple.groovy\n./chap19/v02/Listing_19_05_MainGroovyShell.groovy\n./chap19/v02/Listing_19_07_MainBinding.groovy\n./chap19/v02/Listing_19_08_MainDirectionConstants.groovy\n./chap19/v02/Listing_19_09_MainDirectionsSpread.groovy\n./chap19/v02/Listing_19_10_MainImplicitMethod.groovy\n./chap19/v02/Listing_19_12_MainBaseScript.groovy\n./chap19/v02/Listing_19_13_MainImportCustomizer.groovy\n./chap19/v02/Listing_19_14_MainCustomBaseScriptClass.groovy\n./chap19/v02/Listing_19_16_MainMethodClosure.groovy\n./chap19/v02/Listing_19_19_MainLowerCase.groovy\n./chap19/v02/model/Direction.groovy\n./chap19/v02/model/Robot.groovy\n./chap19/v02/snippet1901_MainFileRunner.groovy\n./chap19/v03/integration/DistanceCategory.groovy\n./chap19/v03/integration/RobotBaseScript.groovy\n./chap19/v03/integration/SuperBotBaseScript.groovy\n./chap19/v03/Listing_19_27_SimpleCommandChain.groovy\n./chap19/v03/Listing_19_39_Robot_With.groovy\n./chap19/v03/model/Direction.groovy\n./chap19/v03/model/Distance.groovy\n./chap19/v03/model/Duration.groovy\n./chap19/v03/model/Robot.groovy\n./chap19/v03/model/Speed.groovy\n./chap19/v03/model/SuperBot.groovy\n./chap19/v03/model/Unit.groovy\n./chap19/xform/BusinessLogicScript.groovy\n./chap19/xform/CustomControlStructure.groovy\n./chap19/xform/extra_WhenTransformationWorksWithoutBraces.groovy\n./chap19/xform/Listing_19_36_WhenTransformation.groovy\n./chap19/xform/snippet1906_WhenUntilXform_Structure.groovy\n./chap19/xform/WhenUntilTransform.groovy\n./chap20/Listing_20_01_Grapes_for_twitter_urls.groovy\n./chap20/Listing_20_02_Scriptom_Windows_only.groovy\n./chap20/Listing_20_03_ActivX_Windows_only.groovy\n./chap20/Listing_20_10_SquaringMapValue.groovy\n./chap20/Listing_20_11_Synchronized.groovy\n./chap20/Listing_20_12_DbC_invariants.groovy\n\n"
  },
  {
    "path": "listings/appD/Listing_D_01_GStrings.groovy",
    "content": "\n// normal use\ndef    g1 =  \"1 + 1 equals ${1 + 1}\"\nassert g1 == '1 + 1 equals 2'\nassert g1 instanceof CharSequence\nassert g1 instanceof GString\n\ndef x = 10\n\ndef    g2 =  \"$x\"   // reference\nassert g2 == \"10\"\n\ndef    g3 =  \"${x}\" // expression\nassert g3 == \"10\"\n\n// lazy evaluation with a writeable closure!\ndef g4 = \"${ -> x}\" // closure\nx = 20              // value change after definition\nassert g4 == \"20\"   // lazy evaluation!\n"
  },
  {
    "path": "listings/appD/Listing_D_02_Lists.groovy",
    "content": "assert [1,2,3,4]       == (1..4)\nassert [1,2,3] + [1]   == [1,2,3,1]\nassert [1,2,3] << 1    == [1,2,3,1]\nassert [1,2,3,1] - [1] == [2,3]\nassert [1,2,3] * 2     == [1,2,3,1,2,3]\nassert [1,[2,3]].flatten() == [1,2,3]\nassert [1,2,3].reverse()   == [3,2,1]\nassert [1,2,3].disjoint([4,5,6])\nassert [1,2,3].intersect([4,3,1]) == [3,1]\nassert [1,2,3].collect{ it+3 }    == [4,5,6]\nassert [1,2,3,1].unique().size()  == 3\nassert [1,2,3,1].count(1) == 2\nassert [1,2,3,4].min()    == 1\nassert [1,2,3,4].max()    == 4\nassert [1,2,3,4].sum()    == 10\nassert [4,2,1,3].sort()   == [1,2,3,4]\nassert [4,2,1,3].findAll{ it%2 == 0 } == [4,2]\ndef animals = ['cat','kangaroo','koala','dog']\nassert animals[2] == 'koala'\ndef kanimals = animals[1..2]\nassert animals.findAll{ it =~ /k.*/ } == kanimals\nassert animals.find{ it =~ /k.*/ }    == kanimals[0]\nassert animals.grep(~/k.*/)           == kanimals\n\n// parallel assignment as swap\ndef a = 1, b = 2\n(a, b)   = [b, a]\nassert a == 2\nassert b == 1\n\n// lesser known methods\n\nassert animals.sort    { it.size() } == ['cat', 'dog', 'koala', 'kangaroo']\nassert animals.max     { it.size() } == 'kangaroo'\nassert animals.groupBy { it.size() } == [ 3:['cat','dog'], 5:['koala'], 8:['kangaroo'] ]\n\nassert [1,2,3].permutations().toList() == [\n    [1, 2, 3], [2, 3, 1], [3, 2, 1], [3, 1, 2], [2, 1, 3], [1, 3, 2]\n]\nassert (1..10).collate(3)  == [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]\n\ndef matrix = [\n    ['a', 'b'],\n    [ 1 ,  2 ]\n]\nassert matrix.transpose()    == [ ['a', 1], ['b', 2] ]\nassert matrix.combinations() == [ ['a', 1], ['b', 1], ['a', 2], ['b', 2] ]\n\n"
  },
  {
    "path": "listings/appD/Listing_D_03_Closures.groovy",
    "content": "def add  = { x, y -> x + y }\ndef mult = { x, y -> x * y }\nassert add(1,3)  == 4\nassert mult(1,3) == 3\ndef min = { x, y -> [x,y].min() }\ndef max = { x, y -> [x,y].max() }\ndef atLeastTen = max.curry(10)\nassert atLeastTen(5)  == 10\nassert atLeastTen(15) == 15\ndef pairWise(list, Closure invoke) {\n    if (list.size() < 2) return []\n    def next = invoke(list[0],list[1])\n    return [next] + pairWise(list[1..-1], invoke)\n}\nassert pairWise(1..5, add)  == [3, 5, 7, 9]\nassert pairWise(1..5, mult) == [2, 6, 12, 20]\nassert pairWise(1..5, min)  == [1, 2, 3, 4]\nassert pairWise(1..5, max)  == [2, 3, 4, 5]\nassert 'cbaxabc' == ['a','b','c'].inject('x') {\n        result, item -> item + result + item\n}\nassert [1,2,3].grep{ it<3 } == [1,2]\nassert [1,2,3].any{ it%2 == 0 }\nassert [1,2,3].every{ it<4 }\nassert (1..9).collect{it}.join()   == '123456789'\nassert (1..4).collect{it*2}.join() == '2468'"
  },
  {
    "path": "listings/appD/Listing_D_04_Regex.groovy",
    "content": "def twister = 'she sells sea shells by the sea shore'\n\n// contains word 'shore'\nassert twister =~ 'shore'\n\n// contains 'sea' twice (two ways)\nassert (twister =~ 'sea').count == 2\nassert twister.split(/ /).grep(~/sea/).size() == 2\n\n// words that start with 'sh', \\b = word boundary\ndef shwords = (twister =~ /sh[a-z]*\\b/).collect{it}.join(' ')\nassert shwords == 'she shells shore'\n\n// sh-words by parallel assignment\ndef (a, b, c) = twister =~ /sh[a-z]*\\b/\nassert a == 'she'\nassert b == 'shells'\nassert c == 'shore'\n\n// four words have three letter, \\S = non-Space letter\nassert (twister =~ /\\b\\S{3}\\b/).count == 4\n\n// three words start with 's' and have 4, 5, or 6 letters\nassert (twister =~ /\\bs\\S{4}\\S?\\b/).count == 3\n\n// replace words with 'X', \\w = word character\nassert twister.replaceAll(/\\w+/,'X') == 'X X X X X X X X'\n\n// starts with 'she' and ends with 'shore'\ndef pattern = ~/she.*shore/\nassert pattern.matcher(twister).matches()\n\n// replace 'sea' with 'ocean' but only if preceded by word 'the'\ndef ocean = twister.replaceAll('(?<=the )sea','ocean')\nassert ocean == 'she sells sea shells by the ocean shore'\n\n// swap 1st and 2nd pairs of words\ndef pairs = twister =~ /(\\S+) (\\S+) ?/\nassert pairs.hasGroup()\ntwister = [1, 0, 2, 3].collect{ pairs[it][0] }.join()\nassert twister == 'sea shells she sells by the sea shore'\n"
  },
  {
    "path": "listings/appD/Listing_D_05_GPath.groovy",
    "content": "import groovy.xml.dom.DOMCategory\n\ndef recipeXml = '''\n<recipe>\n   <ingredients>\n      <ingredient amount='2 cups'>Self-raising Flour</ingredient>\n      <ingredient amount='2 tablespoons'>Icing sugar</ingredient>\n      <ingredient amount='2 tablespoons'>Butter</ingredient>\n      <ingredient amount='3/4 - 1 cup'>Milk</ingredient>\n   </ingredients>\n   <steps>\n      <step>Preheat oven to 230 degrees celsius</step>\n      <step>Sift flour and icing sugar into a bowl</step>\n      <step>Melt butter and mix into dry ingredients</step>\n      <step>Gradually add milk to the mixture until moist</step>\n      <step>Turn onto floured board and cut into portions</step>\n      <step>Bake for 15 minutes</step>\n      <step>Serve with jam and whipped cream</step>\n   </steps>\n</recipe>\n'''\n\ndef recipe  = new XmlSlurper().parseText(recipeXml)\n\nassert 4 == recipe.ingredients.ingredient.size()\n// should be 14 elements in total\nassert 14 == recipe.'**'.findAll{true}.size()\n// step 4 (index 3 because we start from 0) involves milk\nassert recipe.steps.step[3].text().contains('milk')\nassert '2 cups' == recipe.ingredients.ingredient[0].'@amount'.toString()\n// two ingredients have '2 tablespoons' amount attribute\ndef ingredients = recipe.ingredients.ingredient.grep{\n    it.'@amount' == '2 tablespoons'\n}\nassert ingredients.size() == 2\n// every step has at least 4 words\nassert recipe.steps.step.every{\n    step -> step.text().tokenize(' ').size() >= 4\n}\n\n\ndef recipe2  = new XmlParser().parseText(recipeXml)\n/* … processing steps … */\ndef reader  = new StringReader(recipeXml)\ndef doc     = groovy.xml.DOMBuilder.parse(reader)\ndef recipe3  = doc.documentElement\nuse (groovy.xml.dom.DOMCategory) {\n    /* … processing steps … */\n}\n"
  },
  {
    "path": "listings/chap01/Listing_01_01_Gold.groovy",
    "content": "List fibo = [1, 1]                          //#A\nList gold = [1, 2]                          //#B\n\nwhile ( ! isGolden( gold[-1] ) ) {          //#C\n    fibo.add( fibo[-1] + fibo[-2] )         //#D\n    gold.add( fibo[-1] / fibo[-2] )         //#E\n}\n\nprintln \"found golden ratio with fibo(${ fibo.size-1 }) as\"\nprintln fibo[-1] + \" / \" + fibo[-2] + \" = \" + gold[-1]\nprintln \"_\" * 10 +  \"|\"  + \"_\" * (10 * gold[-1])\n\ndef isGolden(candidate) {                   //#F\n    def small = 1                           //#G\n    def big = small * candidate             //#H\n    return isCloseEnough( (small+big)/big, big/small)\n}\n\ndef isCloseEnough(a,b) { return (a-b).abs() < 1.0e-9 }\n//#A Initial Fibonacci numbers\n//#B Golden ration candidates\n//#C Last gold candidate\n//#D Next fibo number\n//#E Next golden candidate\n//#F Candidate satisfies golden rule\n//#G Smaller section\n//#H Bigger section\n"
  },
  {
    "path": "listings/chap01/customers.xml",
    "content": "<?xml version=\"1.0\" ?>\n<customers>\n  <corporate>\n    <customer name=\"Bill Gates\"      company=\"Microsoft\" />\n    <customer name=\"Tim Cook\"        company=\"Apple\"     />\n    <customer name=\"Larry Ellison\"   company=\"Oracle\"    />\n  </corporate>\n  <consumer>\n    <customer name=\"John Doe\" />\n    <customer name=\"Jane Doe\" />\n  </consumer>\n</customers>\n"
  },
  {
    "path": "listings/chap01/data.txt",
    "content": "first line\nsecond line"
  },
  {
    "path": "listings/chap01/groovysh.txt",
    "content": "Groovy Shell (2.4.0, JVM: 1.7.0_75)\nType ':help' or ':h' for help.\n--------------------------------------------------------------------\ngroovy:000> \"Welcome, \" + System.properties.\"user.name\"\n===> Welcome, Dierk\ngroovy:000> "
  },
  {
    "path": "listings/chap01/snippet0101_customers.groovy",
    "content": "def customers = new XmlSlurper().parse(new File('customers.xml'))\nfor (customer in customers.corporate.customer) {\n    println \"${customer.@name} works for ${customer.@company}\"\n}"
  },
  {
    "path": "listings/chap01/snippet0101_fileLineNumbers.groovy",
    "content": "def number = 0\nnew File('data.txt').eachLine { line ->\n    number++\n    println \"$number: $line\"\n}"
  },
  {
    "path": "listings/chap01/snippet0101_newDates.txt",
    "content": "import java.util.*;       // Java\nDate today = new Date();  // Java\n\ntoday = new Date()        // Groovy\n\nrequire 'date'             # Ruby\ntoday = Date.new           # Ruby\n\nimport java.util._        // Scala\nvar today = new Date      // Scala\n\n(import '(java.util Date)) ; Clojure\n(def today (new Date))     ; Clojure\n(def today (Date.))        ; Clojure alternative"
  },
  {
    "path": "listings/chap01/snippet0101_printPackageNames.groovy",
    "content": "def classes = [String, List, File]\nfor (clazz in classes) {\n    println clazz.package.name\n}"
  },
  {
    "path": "listings/chap01/snippet0101_printPackageNamesGpath.groovy",
    "content": "println( [String, List, File]*.package*.name )"
  },
  {
    "path": "listings/chap01/snippet0102_printGroovyWebSiteCount.groovy",
    "content": "import static groovyx.gpars.GParsPool.withPool\n\ndef urls = [\n        'http://www.groovy-lang.org',\n        'http://gpars.codehaus.org',\n        'http://gr8conf.org/'\n]*.toURL()\n\nprintln withPool {\n    urls.collectParallel {\n        it.text.findAll(~/[Gg]roovy/).size()\n    }\n}"
  },
  {
    "path": "listings/chap01/snippet0103_googleIpAdr.groovy",
    "content": "InetAddress.getAllByName(\"google.com\").collect {\n    it.toString().split('/')[1]\n}\n"
  },
  {
    "path": "listings/chap02/Book.groovy",
    "content": "class Book {\n    private String title\n    Book (String theTitle) {\n        title = theTitle\n    }\n    String getTitle(){\n        return title\n    }\n}"
  },
  {
    "path": "listings/chap02/Listing_02_01_Assertions.groovy",
    "content": "assert(true)\nassert 1 == 1\ndef    x =  1\nassert x == 1\ndef    y =  1 ; assert y == 1"
  },
  {
    "path": "listings/chap02/Listing_02_02_Book.txt",
    "content": "see Book.groovy"
  },
  {
    "path": "listings/chap02/Listing_02_03_BookScript.groovy",
    "content": "Book gina = new Book('Groovy in Action')\n\nassert gina.getTitle()         == 'Groovy in Action'\nassert getTitleBackwards(gina) == 'noitcA ni yvoorG'\n\nString getTitleBackwards(book) {\n    String title = book.getTitle()\n    return title.reverse()\n}\n"
  },
  {
    "path": "listings/chap02/Listing_02_04_BookBean.groovy",
    "content": "class BookBean {\n  String title                                         //#A\n}\n\ndef groovyBook = new BookBean()\n\ngroovyBook.setTitle('Groovy in Action')                //#B\nassert groovyBook.getTitle() == 'Groovy in Action'     //#B\n\ngroovyBook.title = 'Groovy conquers the world'         //#C\nassert groovyBook.title == 'Groovy conquers the world' //#C\n//#A Property declaration\n//#B Property use with explicit getter calls\n//#C Property use with Groovy shortcuts\n"
  },
  {
    "path": "listings/chap02/Listing_02_05_ImmutableBook.groovy",
    "content": "import groovy.transform.Immutable\n\n@Immutable class FixedBook {                           //#A\n    String title\n}\n\ndef gina   = new FixedBook('Groovy in Action')         //#B\ndef regina = new FixedBook(title:'Groovy in Action')   //#C\n\nassert gina.title == 'Groovy in Action'\nassert gina == regina                                  //#D\n\ntry {\n    gina.title = \"Oops!\"                               //#E\n    assert false, \"should not reach here\"\n} catch (ReadOnlyPropertyException expected) {\n    println \"Expected Error: '$expected.message'\"\n}\n//#A AST annotation\n//#B Positional constructor\n//#C Named-arg constructor\n//#D Standard equals()\n//#E Not allowed!\n"
  },
  {
    "path": "listings/chap02/Listing_02_06_Grab.groovy",
    "content": "@Grab('commons-lang:commons-lang:2.4')\nimport org.apache.commons.lang.ClassUtils\n\nclass Outer {\n  class Inner {}\n}\n\nassert !ClassUtils.isInnerClass(Outer)\nassert ClassUtils.isInnerClass(Outer.Inner)\n"
  },
  {
    "path": "listings/chap02/Listing_02_07_Clinks.groovy",
    "content": "def totalClinks = 0\ndef partyPeople = 100\n1.upto(partyPeople) { guestNumber ->\n    clinksWithGuest = guestNumber-1\n    totalClinks += clinksWithGuest                     //#A\n}\nassert totalClinks == (partyPeople * (partyPeople-1)) / 2\n//#A Modifies outer scope"
  },
  {
    "path": "listings/chap02/Listing_02_08_ControlStructures.groovy",
    "content": "if (false) assert false                                //#A\n\nif (null)                                              //#B\n{                                                      //#C\n    assert false\n}\nelse\n{\n    assert true\n}\n\ndef i = 0                                              //#D\nwhile (i < 10) {                                       //#D\n    i++                                                //#D\n}                                                      //#D\nassert i == 10                                         //#D\n\ndef clinks = 0                                         //#E\nfor (remainingGuests in 0..9) {                        //#E\n    clinks += remainingGuests                          //#E\n}                                                      //#E\nassert clinks == (10*9)/2                              //#E\n\ndef list = [0, 1, 2, 3]                                //#F\nfor (j in list) {                                      //#F\n    assert j == list[j]                                //#F\n}                                                      //#F\n\nlist.each() { item ->                                  //#G\n    assert item == list[item]                          //#G\n}                                                      //#G\n\nswitch(3)  {                                           //#H\n    case 1 : assert false; break                       //#H\n    case 3 : assert true;  break                       //#H\n    default: assert false                              //#H\n}                                                      //#H\n//#A The if as one-liner\n//#B Null is false\n//#C Blocks may start on new line\n//#D Classic while\n//#E The for in range\n//#F The for in list\n//#G The each method with a closure\n//#H Class switch\n"
  },
  {
    "path": "listings/chap02/snippet0201_comments.groovy",
    "content": "#!/usr/bin/env groovy\n// some line comment\n/* some multi-\n   line comment */"
  },
  {
    "path": "listings/chap02/snippet0202_failing_assert.groovy",
    "content": "def a = 5\ndef b = 9\nassert b == a + a                                      //#A\n//#A expected to fail\n"
  },
  {
    "path": "listings/chap02/snippet0202_failing_assertion_error.txt",
    "content": "Assertion failed:\n\nassert b == a + a                                      //#A\n       | |  | | |\n       9 |  5 | 5                                      //#B\n         |    10                                       //#C\n         false                                         //#C\n\n        at snippet22_failing_assert.run(snippet22_failing_assert.groovy:3)\n#A Expression is retained\n#B Referenced values\n#C Subexpression values\n"
  },
  {
    "path": "listings/chap02/snippet0203_clinks_java.groovy",
    "content": "// Java snippet\nint totalClinks = 0;\nint partyPeople = 100;\nfor(int guestNumber = 1;\n        guestNumber <= partyPeople;\n        guestNumber++) {\n    int clinksWithGuest = guestNumber-1;\n    totalClinks += clinksWithGuest;\n}"
  },
  {
    "path": "listings/chap02/snippet0203_gstring.groovy",
    "content": "def nick = 'ReGina'\ndef book = 'Groovy in Action, 2nd ed.'\nassert \"$nick is $book\" == 'ReGina is Groovy in Action, 2nd ed.'"
  },
  {
    "path": "listings/chap02/snippet0203_int_usage.groovy",
    "content": "def x = 1\ndef y = 2\nassert x + y     == 3\nassert x.plus(y) == 3\nassert x instanceof Integer"
  },
  {
    "path": "listings/chap02/snippet0203_map_usage.groovy",
    "content": "def http = [\n        100 : 'CONTINUE',\n        200 : 'OK',\n        400 : 'BAD REQUEST'\n]\nassert http[200] == 'OK'\nhttp[500] = 'INTERNAL SERVER ERROR'\nassert http.size() == 4"
  },
  {
    "path": "listings/chap02/snippet0203_range_usage.groovy",
    "content": "def x = 1..10\nassert x.contains(5)\nassert !x.contains(15)\nassert x.size() == 10\nassert x.from == 1\nassert x.to == 10\nassert x.reverse() == 10..1"
  },
  {
    "path": "listings/chap02/snippet0203_roman.groovy",
    "content": "def roman = ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII']  //#A\nassert roman[4] == 'IV'                                     //#B\n\nroman[8] = 'VIII'                                           //#C\nassert roman.size() == 9\n//#A List of Roman numerals\n//#B List access\n//#C List expansion\n"
  },
  {
    "path": "listings/chap02/snippet0204_evaluate_jdk7_only.groovy",
    "content": "//java.class.version\n//jdk5=49.0\n//jdk6=50.0\n//jdk7=51.0\n//jdk8=52.0\ndef code = '1 + '\ncode += System.getProperty('java.class.version')\nassert code == '1 + 51.0'\nassert 52.0 == evaluate(code)"
  },
  {
    "path": "listings/chap02/snippet0204_evaluate_jdk8_only.groovy",
    "content": "//java.class.version\n//jdk5=49.0\n//jdk6=50.0\n//jdk7=51.0\n//jdk8=52.0\ndef code = '1 + '\ncode += System.getProperty('java.class.version')\nassert code == '1 + 52.0'\nassert 53.0 == evaluate(code)"
  },
  {
    "path": "listings/chap02/snippet0204_failing_typechecked.groovy",
    "content": "class Universe {\n  @groovy.transform.TypeChecked\n  int answer() { \"forty two\" }\n}\n\nprintln new Universe().answer()\n"
  },
  {
    "path": "listings/chap03/ArrayListSummer.java",
    "content": "public class ArrayListSummer {\n    public static void main(String[] args) {\n        // (60 * 60 * 24 * 365).toString();\n        int secondsPerYear = 60 * 60 * 24 * 365;\n        // secondsPerYear.toString();\n        new Integer(secondsPerYear).toString();\n    }\n}\n"
  },
  {
    "path": "listings/chap03/Listing_03_01_PrimitiveMethodsObjectOperators.groovy",
    "content": "(60 * 60 * 24 * 365).toString();         // invalid Java\n\nint secondsPerYear = 60 * 60 * 24 * 365;\nsecondsPerYear.toString();               // invalid Java\n\nnew Integer(secondsPerYear).toString();\n\nassert \"abc\" - \"a\" == \"bc\"               // invalid Java"
  },
  {
    "path": "listings/chap03/Listing_03_02_ListMapCast.groovy",
    "content": "import java.awt.*\n\nPoint topLeft  = new Point(0, 0) // classic\nPoint botRight = [100, 100]      // List cast\nPoint center   = [x:50, y:50]    // Map cast\n\nassert botRight instanceof Point\nassert center   instanceof Point\n\ndef rect = new Rectangle()\nrect.location = [0, 0]              // Point\nrect.size = [width:100, height:100] // Dimension"
  },
  {
    "path": "listings/chap03/Listing_03_03_DefiningOperators.groovy",
    "content": "import groovy.transform.Immutable\n\n@Immutable                                             //#1\nclass Money {\n    int     amount\n    String  currency\n\n    Money plus (Money other) {                         //#2\n        if (null == other) return this\n        if (other.currency != currency) {\n            throw new IllegalArgumentException(\n                \"cannot add $other.currency to $currency\")\n        }\n        return new Money(amount + other.amount, currency)\n    }        \n}\n\nMoney  buck = new Money(1, 'USD')\nassert buck \nassert buck        == new Money(1, 'USD')              //#3\nassert buck + buck == new Money(2, 'USD')              //#4\n//#1 Overrides == operator\n//#2 Implements + operator\n//#3 Use overridden ==\n//#4 Use implemented +\n"
  },
  {
    "path": "listings/chap03/Listing_03_04_DefiningGStrings.groovy",
    "content": "import static java.util.Calendar.*\n\ndef me       = 'Tarzan'\ndef you      = 'Jane'\ndef line     = \"me $me - you $you\"                            //#1\nassert  line == 'me Tarzan - you Jane'\n\nTimeZone.default =  TimeZone.getTimeZone('GMT')\ndef date = new Date(0)\ndef dateMap = [y:date[YEAR]-1900, m:date[MONTH], d:date[DAY_OF_MONTH]]\ndef out = \"Year $dateMap.y Month $dateMap.m Day $dateMap.d\"   //#2\nassert out == 'Year 70 Month 0 Day 1'\n\ndef tz = TimeZone.getTimeZone('GMT')\ndef format = 'd MMM YYYY HH:mm:SS z'\nout = \"Date is ${date.format(format, tz)} !\"                  //#3\nassert out == 'Date is 1 Jan 1970 00:00:00 GMT !'\n\n                                                              //#4 start\ndef sql = \"\"\"\nSELECT FROM MyTable\n  WHERE Year = $dateMap.y\n\"\"\"\nassert sql == \"\"\"\nSELECT FROM MyTable\n  WHERE Year = 70\n\"\"\"\n                                                              //#4 end\nout = \"my 0.02\\$\"                                             //#A\nassert out == 'my 0.02$'                                      //#B\n//#1 Abbreviated dollar syntax\n//#2 Extended dot syntax\n//#3 Full syntax with braces\n//#4 Multiline GStrings\n//#A Escaped dollar sign\n//#B Literal dollar sign\n"
  },
  {
    "path": "listings/chap03/Listing_03_05_StringOperations.groovy",
    "content": "String greeting = 'Hello Groovy!'\n\nassert greeting.startsWith('Hello')\n\nassert greeting.getAt(0) == 'H'\nassert greeting[0]       == 'H'\n\nassert greeting.indexOf('Groovy') >= 0\nassert greeting.contains('Groovy')\n\nassert greeting[6..11]  == 'Groovy'\n\nassert 'Hi' + greeting - 'Hello' == 'Hi Groovy!' \n\nassert greeting.count('o') == 3\n\nassert 'x'.padLeft(3)      == '  x'\nassert 'x'.padRight(3,'_') == 'x__'\nassert 'x'.center(3)       == ' x '\nassert 'x' * 3             == 'xxx'"
  },
  {
    "path": "listings/chap03/Listing_03_06_RegexGStrings.groovy",
    "content": "assert \"abc\" == /abc/\nassert \"\\\\d\" == /\\d/ \n\ndef reference = \"hello\"\nassert reference == /$reference/\n\nassert \"\\$\" == /$/"
  },
  {
    "path": "listings/chap03/Listing_03_07_RegularExpressions.groovy",
    "content": "def twister = 'she sells sea shells at the sea shore of seychelles'\n\n// twister must contain a substring of size 3 \n// that starts with s and ends with a\nassert twister =~ /s.a/                                        //#1\n\ndef finder = (twister =~ /s.a/)                                //#2\nassert finder instanceof java.util.regex.Matcher               //#2\n\n// twister must contain only words delimited by single spaces\nassert twister ==~ /(\\w+ \\w+)*/                                //#A\n\ndef WORD = /\\w+/\nmatches = (twister ==~ /($WORD $WORD)*/)                       //#B\nassert matches instanceof java.lang.Boolean                    //#B\n\nassert !(twister ==~ /s.e/)                                    //#C\n\ndef wordsByX = twister.replaceAll(WORD, 'x')\nassert wordsByX == 'x x x x x x x x x x'\n\ndef words = twister.split(/ /)                                 //#D\nassert words.size() == 10\nassert words[0] == 'she'\n//#1 Regex find operator as usable in if\n//#2 Find expression evaluates to a matcher object\n//#A Regex match operator\n//#B Match expression evaluates to a boolean\n//#C Match is full unlike find\n//#D Split returns a list of words\n"
  },
  {
    "path": "listings/chap03/Listing_03_08_EachMatch.groovy",
    "content": "def myFairStringy = 'The rain in Spain stays mainly in the plain!'\n\n// words that end with 'ain': \\b\\w*ain\\b\ndef wordEnding = /\\w*ain/\ndef rhyme = /\\b$wordEnding\\b/\ndef found = ''\nmyFairStringy.eachMatch(rhyme) { match ->                      //#1\n    found += match + ' '\n}\nassert found == 'rain Spain plain '\n\nfound = ''\n(myFairStringy =~ rhyme).each { match ->                       //#2\n    found += match + ' '\n}\nassert found == 'rain Spain plain '\n\ndef cloze = myFairStringy.replaceAll(rhyme){ it-'ain'+'___' }  //#3\nassert cloze == 'The r___ in Sp___ stays mainly in the pl___!'\n//#1 String.eachMatch(regex){}\n//#2 Matcher.each {}\n//#3 String.replaceAll(regex){}"
  },
  {
    "path": "listings/chap03/Listing_03_09_PatternReuse.groovy",
    "content": "def twister = 'she sells sea shells at the sea shore of seychelles'\n// some more complicated regex: \n// word that starts and ends with same letter\ndef regex = /\\b(\\w)\\w*\\1\\b/\ndef many  = 100 * 1000\n\nstart = System.nanoTime()\nmany.times{\n    twister =~ regex                                   //#1\n}\ntimeImplicit = System.nanoTime() - start\n\nstart = System.nanoTime()\npattern = ~regex                                       //#A\nmany.times{\n    pattern.matcher(twister)                           //#B\n}\ntimePredef = System.nanoTime() - start\n\nassert timeImplicit > timePredef * 2                   //#C\n//#1 Find operator with implicit pattern construction\n//#A Explicit pattern construction\n//#B Apply pattern on a string\n//#C At least twice as fast (possibly 3–5 times)\n"
  },
  {
    "path": "listings/chap03/Listing_03_10_PatternsClassification.groovy",
    "content": "def fourLetters = ~/\\w{4}/\n\nassert fourLetters.isCase('work')\n\nassert 'love' in fourLetters\n\nswitch('beer'){\n    case fourLetters : assert true; break\n    default          : assert false\n}\n\nbeasts = ['bear','wolf','tiger','regex']\n\nassert beasts.grep(fourLetters) == ['bear','wolf']"
  },
  {
    "path": "listings/chap03/Listing_03_11_NumberMethodsGDK.groovy",
    "content": "def store = ''\n10.times{                                              //#A\n    store += 'x'\n}\nassert store == 'xxxxxxxxxx'\n\nstore = ''\n1.upto(5) { number ->                                  //#B\n    store += number\n}\nassert store == '12345'\n\nstore = ''\n2.downto(-2) { number ->                               //#C\n    store += number + ' '\n}\nassert store == '2 1 0 -1 -2 '\n\nstore = ''\n0.step(0.5, 0.1 ){ number ->                           //#D\n    store += number + ' '\n}\nassert store == '0 0.1 0.2 0.3 0.4 '\n//#A Repetition\n//#B Walking up with loop variable\n//#C Walking down\n//#D Walking with step width\n"
  },
  {
    "path": "listings/chap03/extra_escaped_characters_table36.groovy",
    "content": "println \"A '\\b' Backspace\"\nprintln \"A '\\t' Tab\"\nprintln \"A '\\r' Carriage return\"\nprintln \"A '\\n' Line feed\"\nprintln \"A '\\f' Form feed\"\nprintln \"A '\\\\' Backslash\"\nprintln \"A '\\$' Dollar sign\"\nprintln \"A '\\u00A9' (Copyright symbol) - Unicode character U+00A9\"\nprintln \"A '\\54' (Comma) - ASCII code 44 (44 decimal = 54 octal)\"\nprintln \"A '\\'' Single quote\"\nprintln \"A '\\\"' Double quote\"\n"
  },
  {
    "path": "listings/chap03/extra_method_operators_table34.groovy",
    "content": "def a = 2\ndef b = 3\n\nassert a + b == a.plus(b)\nassert a - b == a.minus(b)\nassert a * b == a.multiply(b)\nassert a / b == a.div(b)\nassert a % b == a.mod(b)\n\na = 2\nassert ++a == 2.next()\nassert a == 3\n\na = 2\nassert a++ == 2\nassert a == 3\n\na = 2\nassert --a == 2.previous()\nassert a == 1\n\na = 2\nassert a-- == 2\nassert a == 1\n\na = 2\nassert -a == a.unaryMinus()\n// added in 2.2.0-beta-2\n//assert (+a) == a.unaryPlus()\n\nassert a ** b == a.power(b)\n\nassert (a | b) == a.or(b)\nassert (a & b) == a.and(b)\nassert (a ^ b) == a.xor(b)\n\n// added in 2.2.0-beta-2\n//assert ~a == a.bitwiseNegate()\n\na = [foo:5]\nassert a['foo'] == a.getAt('foo')\na['bar'] = 6\nassert a == [foo:5, bar:6]\na = [foo:5]\na.putAt('bar', 6)\nassert a == [foo:5, bar:6]\n\na = 2\nassert a << b == a.leftShift(b)\nassert a >> b == a.rightShift(b)\nassert a >>> b == a.rightShiftUnsigned(b)\n\nenum AgeBand {\n  OLD, YOUNG\n  def isCase(Person p) {\n    p.age in 0..21 == (this == AgeBand.YOUNG)\n  }\n}\nclass Person {\n  String name\n  int age\n}\ndef classify(p) {\n  switch(p) {\n    case AgeBand.OLD: return \"$p.name is old!\"\n    case AgeBand.YOUNG: return \"$p.name is young!\"\n  }\n}\nassert classify(new Person(name: 'Tom', age: 15)) == 'Tom is young!'\nassert classify(new Person(name: 'Mary', age: 25)) == 'Mary is old!'\n\nassert a in b == b.isCase(a)\nassert (a != b) == !(a == b)\nassert a <=> b == a.compareTo(b)\nassert a > b == a.compareTo(b) > 0\nassert a >= b == a.compareTo(b) >= 0\nassert a < b == a.compareTo(b) < 0\nassert a <= b == a.compareTo(b) <= 0\nassert a as Integer == a.asType(Integer)\n\n"
  },
  {
    "path": "listings/chap03/extra_numeric_literals_table32.groovy",
    "content": "[15, 0x1234ffff, 0b00110011, 100_000_000].each {\n  assert it instanceof Integer\n}\n[100L, 200l].each{ assert it instanceof Long }\n[1.23f, 4.56F].each{ assert it instanceof Float }\n[1.23d, 4.56D].each{ assert it instanceof Double }\n[123g, 456G, 1G].each{ assert it instanceof BigInteger }\n[1.23, 4.56, 1.4E4, 2.8e4, 1.23g, 1.23G, 1.0, 1.0G, 0E1].each{\n  assert it instanceof BigDecimal\n}\n"
  },
  {
    "path": "listings/chap03/extra_numerical_coercion_table310.groovy",
    "content": "assert 1f*2f instanceof Double\nassert (Byte)1+(Byte)2 instanceof Integer\nassert 1*2L instanceof Long\n\nassert 1 + 0.5     == 1.5\nassert 1/2 instanceof BigDecimal\nassert (1/2)       == 0.5\nassert (int)(1/2)  == 0\nassert 1.intdiv(2) == 0\n\n// no coercion when exceeding range with +\ndef a = Integer.MAX_VALUE\nassert (a+1) instanceof Integer\nassert (a+1) == Integer.MIN_VALUE\nassert (a+1L) instanceof Long\nassert (a+1G) instanceof BigInteger\n\n// but does coerce with the power operator\nassert 2**30 instanceof Integer\nassert 2**31 instanceof BigInteger\nassert 2**3.5 instanceof Double\nassert 2G+1G  instanceof BigInteger\nassert 2.5G+1G  instanceof BigDecimal\n\nassert 0G == 0.0f\nassert 1.5G == 1.5f\nassert !(1.1G == 1.1f)\n"
  },
  {
    "path": "listings/chap03/extra_optional_typing_table33.groovy",
    "content": "def a = 1;      assert a instanceof Integer   //|#1\ndef b = 1.0f;   assert b instanceof Float     //|#1\n\nint c = 1;      assert c instanceof Integer   //|#2\nfloat d = 1;    assert d instanceof Float     //|#2\n\nInteger e = 1;  assert e instanceof Integer   //|#3\nString f = '1'; assert f instanceof String    //|#3"
  },
  {
    "path": "listings/chap03/extra_primitive_values_table31.groovy",
    "content": "byte    a = 0       ; assert a instanceof Byte \nshort   b = 0       ; assert b instanceof Short\nint     c = 0       ; assert c instanceof Integer\nlong    d = 0L      ; assert d instanceof Long\nfloat   e = 0F      ; assert e instanceof Float\ndouble  f = 0D      ; assert f instanceof Double\nchar    g = 'a'     ; assert g instanceof Character\nboolean h = true    ; assert h instanceof Boolean\n"
  },
  {
    "path": "listings/chap03/regex_dgm.txt",
    "content": "Matcher\nlong size()\nint getCount()\nObject getAt( int idx)\nvoid setIndex( int idx)\nboolean hasGroup()\n\nPattern\nboolean isCase(Object switchValue)\n\nString\nPattern bitwiseNegate()\n\nString replaceFirst(Pattern pattern, String replacement)\nboolean matches(Pattern pattern)\nString minus(Object target) // if (target instanceof Pattern)\nObject splitEachLine(String regex) {match -> ... }\n\nString replaceAll(String regex) {match -> ... }\nString replaceAll(Pattern pattern, String replacement)\n\nString find(String regex)\nString find(Pattern pattern)\n\nString find(String regex) {match -> ... }\nString find(Pattern pattern) {match -> ... }\n\nList findAll(String regex)\nList findAll(Pattern pattern)\n\nList findAll(String regex) {match -> ... }\nList findAll(Pattern pattern) {match -> ... }\n\nString eachMatch(String regex) {match -> ... }\nString eachMatch(Pattern pattern) {match -> ... }\n\nFile\nObject splitEachLine(String sep) {match -> ... }\n\nReader\nObject splitEachLine(String sep) {match -> ... }\n\nInputStream\nObject splitEachLine(String sep, String charset) {match -> ... } \n\nObject splitEachLine(String sep) {match -> ... } "
  },
  {
    "path": "listings/chap03/snippet0301_autoboxing.groovy",
    "content": "assert 'ABCDE'.indexOf(67) == 2\n"
  },
  {
    "path": "listings/chap03/snippet0304_GString_internals.groovy",
    "content": "def me      = 'Tarzan'\ndef you     = 'Jane'\ndef line    = \"me $me - you $you\"\nassert line == 'me Tarzan - you Jane'\nassert line instanceof GString\nassert line.strings[0] == 'me '\nassert line.strings[1] == ' - you '\nassert line.values[0]  == 'Tarzan'\nassert line.values[1]  == 'Jane'"
  },
  {
    "path": "listings/chap03/snippet0304_stringbuffer.groovy",
    "content": "def greeting = 'Hello'\n\ngreeting <<= ' Groovy'                                 //#1\n\nassert greeting instanceof java.lang.StringBuffer\n\ngreeting << '!'                                        //#2\n\nassert greeting.toString() == 'Hello Groovy!'\n\ngreeting[1..4] = 'i'                                   //#A\n\nassert greeting.toString() == 'Hi Groovy!'\n//#1 Left shift and assign\n//#2 Left shift on StringBuffer\n//#A Substring 'ello' becomes 'i'\n"
  },
  {
    "path": "listings/chap03/snippet0305_matcher_each_group.groovy",
    "content": "def matcher = 'a:1 b:2 c:3' =~ /(\\S+):(\\S+)/\nmatcher.each { full, key, value  ->\n    assert full.size()  == 3\n    assert key.size()   == 1  // a,b,c\n    assert value.size() == 1  // 1,2,3\n}"
  },
  {
    "path": "listings/chap03/snippet0305_matcher_groups.groovy",
    "content": "def matcher = 'a:1 b:2 c:3' =~ /(\\S+):(\\S+)/\n\nassert matcher.hasGroup()\nassert matcher[0] == ['a:1', 'a', '1']  // 1st match\nassert matcher[1][2] == '2'             // 2nd match, 2nd group"
  },
  {
    "path": "listings/chap03/snippet0305_matcher_parallel_assignment.groovy",
    "content": "def (a,b,c) = 'a b c' =~ /\\S/ \n\nassert a == 'a' \nassert b == 'b' \nassert c == 'c'"
  },
  {
    "path": "listings/chap03/snippet0305_matcher_plain.groovy",
    "content": "def matcher = 'a b c' =~ /\\S/\n\nassert matcher[0]     == 'a'\nassert matcher[1..2]  == ['b','c']\nassert matcher.size() == 3"
  },
  {
    "path": "listings/chap03/snippet0306_GDK_methods_for_numbers.groovy",
    "content": "assert 1 == (-1).abs()\nassert 2 == 2.5.toInteger()         // conversion\nassert 2 == 2.5 as Integer          // enforced coercion\nassert 2 == (int) 2.5               // cast\nassert 3 == 2.5f.round()\nassert 3.142 ==  Math.PI.round(3)\nassert 4 == 4.5f.trunc()\nassert 2.718 == Math.E.trunc(3)\n\nassert '2.718'.isNumber()           // String methods\nassert 5 == '5'.toInteger()\nassert 5 == '5' as Integer\nassert 53 == (int) '5'              // gotcha!\nassert '6 times' == 6 + ' times'    // Number + String"
  },
  {
    "path": "listings/chap04/Listing_04_01_range_declarations.groovy",
    "content": "assert (0..10).contains(0)                             //#A\nassert (0..10).contains(5)                             //#A\nassert (0..10).contains(10)                            //#A\n\nassert (0..10).contains(-1) == false                   //#A\nassert (0..10).contains(11) == false                   //#A\n\nassert (0..<10).contains(9)                            //#B\nassert (0..<10).contains(10) == false                  //#B\n\ndef a = 0..10                                          //#1\nassert a instanceof Range                              //#1\nassert a.contains(5)                                   //#1\n\na = new IntRange(0,10)                                 //#C\nassert a.contains(5)                                   //#C\n\nassert (0.0..1.0).contains(1.0)                        //#D\nassert (0.0..1.0).containsWithinBounds(0.5)            //#D\n\ndef today     = new Date()                             //#2\ndef yesterday = today - 1                              //#2\nassert (yesterday..today).size() == 2                  //#2\n\nassert ('a'..'c').contains('b')                        //#3\n\ndef log = ''                                           //#E\nfor (element in 5..9){                                 //#E\n    log += element                                     //#E\n}                                                      //#E\nassert log == '56789'                                  //#E\n\nlog = ''                                               //#F\nfor (element in 9..5){                                 //#F\n    log += element                                     //#F\n}                                                      //#F\nassert log == '98765'                                  //#F\n\nlog = ''                                               //#4\n(9..<5).each { element ->                              //#4\n    log += element                                     //#4\n}                                                      //#4\nassert log == '9876'                                   //#4\n//#A Inclusive ranges\n//#B Half-exclusive ranges\n//#1 References to ranges\n//#C Explicit construction\n//#D Bounds checking\n//#2 Date ranges\n//#3 String ranges\n//#E for-in-range loop\n//#F Loop with reverse range\n//#4 Half-exclusive, reverse, each with closure\n"
  },
  {
    "path": "listings/chap04/Listing_04_02_ranges_are_objects.groovy",
    "content": "def result = ''                                        //#A\n(5..9).each { element ->                               //#A\n    result += element                                  //#A\n}                                                      //#A\nassert result == '56789'                               //#A\n\nassert 5 in 0..10                                      //#1\nassert (0..10).isCase(5)                               //#1\n                                                       //#1\ndef age = 36                                           //#1\nswitch(age){                                           //#1\n    case 16..20 : insuranceRate = 0.05 ; break         //#1\n    case 21..50 : insuranceRate = 0.06 ; break         //#1\n    case 51..65 : insuranceRate = 0.07 ; break         //#1\n    default: throw new IllegalArgumentException()      //#1\n}                                                      //#1\nassert insuranceRate == 0.06                           //#1\n                                                  \ndef ages = [20, 36, 42, 56]                            //#2\ndef midage = 21..50                                    //#2\nassert ages.grep(midage) == [36, 42]                   //#2\n//#A Iterating over a range\n//#1 Ranges for classification\n//#2 Filtering with ranges\n"
  },
  {
    "path": "listings/chap04/Listing_04_03_custom_ranges.groovy",
    "content": "class Weekday implements Comparable {\n  static final DAYS = [\n      'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'\n  ]\n  private int index = 0\n\n  Weekday(String day) {                                //#A\n    index = DAYS.indexOf(day)\n  }\n\n  Weekday next() {\n    return new Weekday(DAYS[(index + 1) % DAYS.size()])\n  }\n\n  Weekday previous() {\n    return new Weekday(DAYS[index - 1])                //#1\n  }\n\n  int compareTo(Object other) {\n    return this.index <=> other.index\n  }\n\n  String toString() {\n    return DAYS[index]\n  }\n}\n\ndef mon = new Weekday('Mon')\ndef fri = new Weekday('Fri')\n\ndef worklog = ''\nfor (day in mon..fri) {                                //#B\n  worklog += day.toString() + ' '\n}\nassert worklog == 'Mon Tue Wed Thu Fri '\n//#A Allow all values\n//#1 Range bound methods\n//#B Working through the week\n"
  },
  {
    "path": "listings/chap04/Listing_04_04_list_declarations.groovy",
    "content": "List myList = [1, 2, 3]\n\nassert myList.size() == 3\nassert myList[0]     == 1\nassert myList instanceof ArrayList\n\nList emptyList = []\nassert emptyList.size() == 0\n\nList longList = (0..1000).toList()\nassert longList[555] == 555\n\nList explicitList = new ArrayList()\nexplicitList.addAll(myList)                            //#1\nassert explicitList.size() == 3\nexplicitList[0] = 10\nassert explicitList[0] == 10\n\nexplicitList = new LinkedList(myList)                  //#1\nassert explicitList.size() == 3\nexplicitList[0] = 10\nassert explicitList[0] == 10\n//#1 Fill from myList\n\n//////////////////////// extra examples:\nassert args instanceof String[]                        //#2\nassert args.size() == 0                                //#3\n\nList flat = [0, *myList, 4]                            //#4\nassert flat == [0, 1, 2, 3, 4]\n//#2 Command-line args\n//#3 Array as list\n//#4 Spread"
  },
  {
    "path": "listings/chap04/Listing_04_05_list_subscript_operator.groovy",
    "content": "def myList = ['a','b','c','d','e','f']\n\nassert myList[0..2]  == ['a','b','c']                  //#A\nassert myList[0,2,4] == ['a','c','e']                  //#B\n\nmyList[0..2] = ['x','y','z']                           //#C\nassert myList == ['x','y','z','d','e','f']\n\nmyList[3..5] = []                                      //#1\nassert myList == ['x','y','z']\n\nmyList[1..1] = [0, 1, 2]                               //#2\nassert myList == ['x', 0, 1, 2, 'z']\n//#A getAt(Range)\n//#B getAt(collection of indexes)\n//#C putAt(Range)\n//#1 Removing elements\n//#2 Adding elements\n"
  },
  {
    "path": "listings/chap04/Listing_04_06_list_add_remove.groovy",
    "content": "myList = []\n\nmyList += 'a'                                          //#A\nassert myList == ['a']\n\nmyList += ['b','c']                                    //#B\nassert myList == ['a','b','c']\n\nmyList = []\nmyList <<  'a' << 'b'                                  //#C\nassert myList == ['a','b']\n\nassert myList - ['b'] == ['a']                         //#D\n\nassert myList * 2 == ['a','b','a','b']                 //#E\n//#A plus(Object)\n//#B plus(Collection)\n//#C leftShift is like append\n//#D minus(Collection)\n//#E Multiply\n"
  },
  {
    "path": "listings/chap04/Listing_04_07_lists_control_structures.groovy",
    "content": "myList = ['a', 'b', 'c']\n\nassert myList.isCase('a')\nassert 'b' in myList\n\ndef candidate = 'c'\nswitch(candidate){\n    case myList : assert true; break                   //#1\n    default     : assert false\n}\n\nassert ['x','a','z'].grep(myList) == ['a']             //#2\n\nmyList = []\nif (myList) assert false                               //#3\n\n// Lists can be iterated with a 'for' loop\ndef expr = ''\nfor (i in [1,'*',5]){                                  //#4\n    expr += i\n}\nassert expr == '1*5'\n//#1 Classify by containment\n//#2 Intersection filter\n//#3 Empty lists are false\n//#4 for in Collection\n"
  },
  {
    "path": "listings/chap04/Listing_04_08_list_content_manipulation.groovy",
    "content": "assert [1,[2,3]].flatten() == [1,2,3]\nassert [1,2,3].intersect([4,3,1])== [3,1]\nassert [1,2,3].disjoint([4,5,6])\n\nlist = [1,2,3]\npopped = list.pop()                                    //#1\nassert popped == 3\nassert list == [1,2]\n\nassert [1,2].reverse() == [2,1]\nassert [3,1,2].sort() == [1,2,3]\n\nlist = [ [1,0], [0,1,2] ]\nlist = list.sort { a,b -> a[0] <=> b[0] }              //#2\nassert list == [ [0,1,2], [1,0] ]\n\nlist = list.sort { item -> item.size() }               //#3\nassert list == [ [1,0], [0,1,2] ]\n\nlist = ['a','b','c']\nlist.remove(2)                                         //#4\nassert list == ['a','b']\nlist.remove('b')                                       //#5\nassert list == ['a']\n\nlist = ['a','b','b','c']\nlist.removeAll(['b','c'])\nassert list == ['a']\n\ndef doubled = [1,2,3].collect{ item ->                 //#6\n  item*2\n}\nassert doubled == [2,4,6]\n\ndef odd = [1,2,3].findAll{ item ->                     //#7\n  item % 2 == 1\n}\nassert odd == [1,3]\n//#1 Treating a list like a stack\n//#2 Comparing lists by first element\n//#3 Comparing lists by size\n//#4 Removing by index\n//#5 Removing by value\n//#6 Transforming one list into another\n//#7 Finding every element matching the closure\n\n"
  },
  {
    "path": "listings/chap04/Listing_04_09_list_other_methods.groovy",
    "content": "def list = [1, 2, 3]\n\nassert list.first()  == 1\nassert list.head()   == 1\nassert list.tail()   == [2, 3]\nassert list.last()   == 3\nassert list.count(2) == 1                              //#A\nassert list.max()    == 3                              //#A\nassert list.min()    == 1                              //#A\n                                                       //#A\ndef even = list.find { item ->                         //#A\n    item % 2 == 0                                      //#A\n}                                                      //#A\nassert even == 2                                       //#A\n                                                       //#A\nassert list.every { item -> item < 5 }                 //#A\nassert list.any   { item -> item < 2 }                 //#A\n\ndef store = ''\nlist.each { item ->                                    //#B\n    store += item                                      //#B\n}                                                      //#B\nassert store == '123'                                  //#B\n                                                       //#B\nstore = ''                                             //#B\nlist.reverseEach { item ->                             //#B\n    store += item                                      //#B\n}                                                      //#B\nassert store == '321'                                  //#B\n                                                       //#B\nstore = ''                                             //#B\nlist.eachWithIndex { item, index ->                    //#B\n    store += \"$index:$item \"                           //#B\n}                                                      //#B\nassert store == '0:1 1:2 2:3 '                         //#B\n\nassert list.join('-') == '1-2-3'                       //#C\n                                                       //#C\nresult = list.inject(0) { clinks, guests ->            //#C\n    clinks + guests                                    //#C\n}                                                      //#C\nassert result == 0 + 1 + 2 + 3                         //#C\nassert list.sum() == 6                                 //#C\n                                                       //#C\nfactorial = list.inject(1) { fac, item ->              //#C\n    fac * item                                         //#C\n}                                                      //#C\nassert factorial == 1 * 1 * 2 * 3                      //#C\n//#A Querying\n//#B Iteration\n//#C Accumulation"
  },
  {
    "path": "listings/chap04/Listing_04_10_list_quicksort.groovy",
    "content": "def quickSort(list) {\n  if (list.size() < 2) return list\n  def pivot  = list[list.size().intdiv(2)]\n  def left   = list.findAll { item -> item <  pivot }      //#1\n  def middle = list.findAll { item -> item == pivot }      //#1\n  def right  = list.findAll { item -> item >  pivot }      //#1\n  return quickSort(left) + middle + quickSort(right)       //#A\n}\n\nassert quickSort([])                 == []\nassert quickSort([1])                == [1]\nassert quickSort([1,2])              == [1,2]\nassert quickSort([2,1])              == [1,2]\nassert quickSort([3,1,2])            == [1,2,3]\nassert quickSort([3,1,2,2])          == [1,2,2,3]\nassert quickSort([1.0f,'a',10,null]) == [null,1.0f,10,'a'] //#2\nassert quickSort('bca')              == 'abc'.toList()     //#3\n//#1 Classify by pivot\n//#A Recursive calls\n//#2 Ducktyped items\n//#3 Ducktyped structure\n"
  },
  {
    "path": "listings/chap04/Listing_04_11_list_mapreduce.groovy",
    "content": "def urls = [\n    new URL('http', 'myshop.com', 80, 'index.html'),\n    new URL('https', 'myshop.com', 443, 'buynow.html'),\n    new URL('ftp', 'myshop.com', 21, 'downloads')\n]\n\nassert urls\n    .findAll{ it.port < 99 }\n    .collect{ it.file.toUpperCase() }\n    .sort()\n    .join(', ') == 'DOWNLOADS, INDEX.HTML'\n"
  },
  {
    "path": "listings/chap04/Listing_04_12_map_declarations.groovy",
    "content": "def myMap = [a:1, b:2, c:3]\n\nassert myMap instanceof LinkedHashMap\nassert myMap.size() == 3\nassert myMap['a']   == 1\n\ndef emptyMap = [:]\nassert emptyMap.size() == 0\n\ndef explicitMap = new TreeMap()\nexplicitMap.putAll(myMap)\nassert explicitMap['a'] == 1\n\ndef composed     = [x:'y', *:myMap]                    //#A\nassert composed == [x:'y', a:1, b:2, c:3]\n//#A Spread operator\n"
  },
  {
    "path": "listings/chap04/Listing_04_13_map_accessors.groovy",
    "content": "def myMap = [a:1, b:2, c:3]\n\nassert myMap['a']       == 1                           //#A\nassert myMap.a          == 1                           //#A\nassert myMap.get('a')   == 1                           //#A\nassert myMap.get('a',0) == 1                           //#A\n\nassert myMap['d']       == null                        //#B\nassert myMap.d          == null                        //#B\nassert myMap.get('d')   == null                        //#B\n\nassert myMap.get('d',0) == 0                           //#C\nassert myMap.d          == 0                           //#C\n\nmyMap['d'] = 1                                         //#D\nassert myMap.d == 1                                    //#D\nmyMap.d = 2                                            //#D\nassert myMap.d == 2                                    //#D\n//#A Retrieve existing elements\n//#B Attempt to retrieve missing elements\n//#C Default value\n//#D Single putAt\n"
  },
  {
    "path": "listings/chap04/Listing_04_14_map_query_methods.groovy",
    "content": "def myMap = [a:1, b:2, c:3]\ndef other = [b:2, c:3, a:1]\n\nassert myMap == other                                  //#A\n\nassert !myMap.isEmpty()                                //#B\nassert myMap.size()     == 3                           //#B\nassert myMap.containsKey('a')                          //#B\nassert myMap.containsValue(1)                          //#B\nassert myMap.entrySet() instanceof Collection          //#B\n\nassert myMap.any   {entry -> entry.value > 2  }        //#1\nassert myMap.every {entry -> entry.key   < 'd'}        //#1\nassert myMap.keySet() == ['a','b','c'] as Set          //#C\nassert myMap.values().toList() == [1, 2, 3]            //#D\n//#A Call to equals\n//#B JDK methods\n//#1 GDK methods\n//#C Set equals\n//#D List equals\n"
  },
  {
    "path": "listings/chap04/Listing_04_15_map_iteration.groovy",
    "content": "def myMap = [a:1, b:2, c:3]\n\ndef store = ''\nmyMap.each { entry ->                                  //#A\n    store += entry.key                                 //#A\n    store += entry.value                               //#A\n}                                                      //#A\nassert store == 'a1b2c3'\n\nstore = ''\nmyMap.each { key, value ->                             //#B\n    store += key                                       //#B\n    store += value                                     //#B\n}                                                      //#B\nassert store == 'a1b2c3'\n\nstore = ''\nfor (key in myMap.keySet()) {                          //#C\n    store += key                                       //#C\n}                                                      //#C\nassert store == 'abc'\n\nstore = ''\nfor (value in myMap.values()) {                        //#D\n    store += value                                     //#D\n}                                                      //#D\nassert store == '123'\n//#A Iterate over entries\n//#B Iterate over keys/values\n//#C Iterate over just the keys\n//#D Iterate over just the values\n"
  },
  {
    "path": "listings/chap04/Listing_04_16_map_content.groovy",
    "content": "def myMap = [a:1, b:2, c:3]\nmyMap.clear()\nassert myMap.isEmpty()\n\nmyMap = [a:1, b:2, c:3]\nmyMap.remove('a')\nassert myMap.size() == 2\n\nassert [a:1] + [b:2] == [a:1, b:2]\n\nmyMap = [a:1, b:2, c:3]\ndef abMap = myMap.subMap(['a', 'b'])                     //#1\nassert abMap.size() == 2\n\nabMap = myMap.findAll   { entry -> entry.value < 3 }\nassert abMap.size() == 2\nassert abMap.a      == 1\n\ndef found = myMap.find  { entry -> entry.value < 2 }\nassert found.key   == 'a'\nassert found.value == 1\n\ndef doubled = myMap.collect { entry -> entry.value *= 2 }\nassert doubled instanceof List\nassert doubled.every    { item -> item % 2 == 0 }\n\ndef addTo = []\nmyMap.collect(addTo)    { entry -> entry.value *= 2 }\nassert addTo instanceof List\nassert addTo.every      { item -> item % 2 == 0 }\n//#1 Create a view onto the original map\n"
  },
  {
    "path": "listings/chap04/Listing_04_17_map_example.groovy",
    "content": "def textCorpus = \n\"\"\"\nLook for the bare necessities\nThe simple bare necessities\nForget about your worries and your strife\nI mean the bare necessities\nOld Mother Nature's recipes\nThat bring the bare necessities of life\n\"\"\"\n\ndef words = textCorpus.tokenize()\ndef wordFrequency = [:]\nwords.each { word ->\n  wordFrequency[word] = wordFrequency.get(word,0) + 1  //#1\n}\ndef wordList = wordFrequency.keySet().toList()\nwordList.sort { wordFrequency[it] }                    //#2\n\ndef statistic = \"\\n\"\nwordList[-1..-5].each { word ->\n  statistic += word.padLeft(12)    + ': '\n  statistic += wordFrequency[word] + \"\\n\"\n}\nassert statistic == \"\"\"\n necessities: 4\n        bare: 4\n         the: 3\n        your: 2\n        life: 1\n\"\"\"\n//#1 Update frequency count\n//#2 Sort by frequency\n"
  },
  {
    "path": "listings/chap04/extra_EnumRange.groovy",
    "content": "enum Month {\n    Jan, Feb, Mar, Apr, May, Jun,\n    Jul, Aug, Sep, Oct, Nov, Dec\n}\ndef noClams   = Month.May .. Month.Aug\ndef thisMonth = Month.Aug\n\nboolean iWarnedYou  = false\nif (thisMonth in noClams) {                            //#1\n    println \"Don't eat clams this month,\"\n    println \"it has no 'r' in its name!\"\n    iWarnedYou = true\n}\nassert iWarnedYou\n//#1 'in' operator"
  },
  {
    "path": "listings/chap04/extra_ListCast.groovy",
    "content": "Set names = ['Dierk', 'Paul'] as Set\nassert names instanceof Set\n\nassert names.toListString() ==~ /\\[\\w+, \\w+\\]/\nassert names.asList() instanceof List\n\njava.awt.Point p = [10, 20]\nassert p.x == 10"
  },
  {
    "path": "listings/chap04/extra_ListTable.groovy",
    "content": "def table = [\n    [0, 1],\n    [2, 3]\n]\ntable = table.collectNested { item -> item + 1 }\nassert table == [\n    [1, 2],\n    [3, 4]\n]\nassert table.transpose() == [\n    [1, 3],\n    [2, 4]\n]\nassert table.combinations() == [\n    [1, 3], [2, 3], [1, 4], [2, 4]\n]"
  },
  {
    "path": "listings/chap04/extra_Map_as.groovy",
    "content": "def absComp = [\n    compare: { a,b -> a.abs() <=> b.abs() } \n]\ndef list = [-3, -1, 2]\nlist.sort(true, absComp as Comparator)\nassert list == [-1, 2, -3]"
  },
  {
    "path": "listings/chap04/extra_Map_group.groovy",
    "content": "def tzones = [\n    dierk: +1, guillaume: +1, jon: 0,\n    paul:  +9, tara: -7\n]\nassert tzones.groupBy { key, val -> val.intdiv 5 } == [\n    0: [dierk:1, guillaume:1, jon:0],\n    1: [paul: 9],\n (-1): [tara:-7]\n]   "
  },
  {
    "path": "listings/chap04/extra_MaxMinSum.groovy",
    "content": "def kings = ['Dierk', 'Paul']\nassert kings.max { item -> item.size() } == 'Dierk'\nassert kings.min { item -> item.size() } == 'Paul'\nassert kings.sum { item -> item.size() } == 9\n"
  },
  {
    "path": "listings/chap04/extra_SplitList.groovy",
    "content": "def list = [0, 3, 2, 1]\ndef (small, big) = list.split { it < 2 }\nassert small == [0, 1]\nassert big   == [3, 2]\n\ndef group = list.groupBy { it % 2 }\nassert group[0] == [0, 2]\nassert group[1] == [3, 1]\n"
  },
  {
    "path": "listings/chap04/snippet0402_ListAsSet.groovy",
    "content": "def x = [1, 1, 1]\nassert [1] == new HashSet(x).toList()\nassert [1] == x.unique()\nassert [1] == [1, '1'].unique { item -> item.toInteger() }"
  },
  {
    "path": "listings/chap04/snippet0402_ListRemoveNulls.groovy",
    "content": "List x = [1, null, null, 2]\n\nassert [1, 2] == x.findAll { it != null }\nassert [1, 2] == x.grep { it }\n\nassert [1, 2] == x - [null]\n\nx.removeAll([null])\nassert [1, 2] == x"
  },
  {
    "path": "listings/chap04/snippet0402_ListStreams_jdk8_plus.groovy",
    "content": "def urls = [\n    new URL('http', 'myshop.com', 80, 'index.html'),\n    new URL('https', 'myshop.com', 443, 'buynow.html'),\n    new URL('ftp', 'myshop.com', 21, 'downloads')\n]\n\n// Groovy with Java 8\nimport java.util.stream.Collectors\ndef commaSep = Collectors.joining(\", \")\nassert urls.stream()\n    .filter{ it.port < 99 }\n    .map{ it.file.toUpperCase() }\n    .sorted()\n    .collect(commaSep) == 'DOWNLOADS, INDEX.HTML'\n"
  },
  {
    "path": "listings/chap04/snippet0403_Map_Ctor_Expression.groovy",
    "content": "def x = 'a'\nassert ['x':1] == [x:1]\nassert ['a':1] == [(x):1]"
  },
  {
    "path": "listings/chap04/snippet0403_Map_Ctor_Unquoted.groovy",
    "content": "assert ['a':1] == [a:1]"
  },
  {
    "path": "listings/chap04/snippet0403_Map_MapReduce.groovy",
    "content": "def people = [peter: 40, paul: 30, mary: 20]\nassert people\n    .findAll{ _, age -> age < 35 }\n    .collect{ name, _ -> name.toUpperCase() }\n    .sort()\n    .join(', ') == 'MARY, PAUL'\n"
  },
  {
    "path": "listings/chap04/snippet0403_Map_String_accessors.groovy",
    "content": "def myMap = ['a.b':1]\nassert myMap.'a.b' == 1"
  },
  {
    "path": "listings/chap05/Listing_05_01_closure_simple_declaration.groovy",
    "content": "def log = ''\n(1..10).each { counter -> log += counter }\nassert log == '12345678910'\n\nlog = ''\n(1..10).each { log += it }\nassert log == '12345678910'"
  },
  {
    "path": "listings/chap05/Listing_05_02_simple_method_closure.groovy",
    "content": "class SizeFilter {\n    Integer limit\n\n    boolean sizeUpTo(String value) {\n        return value.size() <= limit\n    }\n}\n\nSizeFilter filter6 = new SizeFilter(limit:6)           //#1\nSizeFilter filter5 = new SizeFilter(limit:5)           //#1\n\nClosure sizeUpTo6 = filter6.&sizeUpTo                  //#2\n\ndef words = ['long string', 'medium', 'short', 'tiny']\n\nassert 'medium' == words.find (sizeUpTo6)              //#3\nassert 'short'  == words.find (filter5.&sizeUpTo)      //#4\n//#1 GroovyBean constructor calls\n//#2 Method closure assignment\n//#3 Calling with closure\n//#4 Passing a method closure directly\n"
  },
  {
    "path": "listings/chap05/Listing_05_03_multi_method_closure.groovy",
    "content": "class MultiMethodSample {\n    \n    int mysteryMethod (String value) {\n        return value.length()\n    }\n    int mysteryMethod (List list) {\n        return list.size()\n    }\n    int mysteryMethod (int x, int y) {\n        return x+y\n    }\n}\n\nMultiMethodSample instance = new MultiMethodSample()\nClosure multi = instance.&mysteryMethod                //#1\n\nassert 10 == multi ('string arg')                      //#2\nassert  3 == multi (['list', 'of', 'values'])          //#2\nassert 14 == multi (6, 8)                              //#2\n//#1 Only a single closure is created\n//#2 Different implementations are called based on argument types\n"
  },
  {
    "path": "listings/chap05/Listing_05_04_closure_all_declarations.groovy",
    "content": "Map map = ['a':1, 'b':2]\nmap.each{ key, value -> map[key] = value * 2 }         //#1\nassert map == ['a':2, 'b':4]\n\nClosure doubler = {key, value -> map[key] = value * 2 }//#2\nmap.each(doubler)                                      //#2\nassert map == ['a':4, 'b':8]\n\ndef doubleMethod (entry){                              //#3\n    entry.value = entry.value * 2                      //#3\n}\ndoubler = this.&doubleMethod                           //#4\nmap.each(doubler)                                      //#4\nassert map == ['a':8, 'b':16]\n//#1 Parameter sequence with commas\n//#2 Assign and then call a closure reference\n//#3 Usual method declaration\n//#4 Reference and call a method as a closure\n"
  },
  {
    "path": "listings/chap05/Listing_05_05_simple_closure_calling.groovy",
    "content": "def adder = { x, y -> return x+y }\n\nassert adder(4, 3) == 7\nassert adder.call(2, 6) == 8\n"
  },
  {
    "path": "listings/chap05/Listing_05_06_calling_closures.groovy",
    "content": "def benchmark(int repeat, Closure worker) {            //#1\n    def start = System.nanoTime()                      //#2\n\n    repeat.times { worker(it) }                        //#3\n\n    def stop = System.nanoTime()                       //#4\n    return stop - start                                //#4\n}\ndef slow = benchmark(10000) { (int) it / 2 }           //#5\ndef fast = benchmark(10000) { it.intdiv(2) }           //#5\nassert fast * 2 < slow                                 //#5\n//#1 Put closures last\n//#2 Some pre-work\n//#3 Call closure the given number of times\n//#4 Some post-work\n//#5 Pass different closures for analysis"
  },
  {
    "path": "listings/chap05/Listing_05_07_simple_currying.groovy",
    "content": "def mult  = { x, y -> return x * y }\ndef twoTimes = mult.curry(2)\nassert twoTimes(5) == 10"
  },
  {
    "path": "listings/chap05/Listing_05_08_logging_curry_example.groovy",
    "content": "def configurator = { format, filter, line ->                //#1\n  filter(line) ?  format(line) : null                       //#1\n}\ndef appender = { config, append, line ->                    //#2\n  def out = config(line)                                    //#2\n  if (out) append(out)                                      //#2\n}\n\ndef dateFormatter   = { line -> \"${new Date()}: $line\" }    //#3\ndef debugFilter     = { line -> line.contains('debug') }    //#3\ndef consoleAppender = { line -> println line }              //#3\n\ndef myConf = configurator.curry(dateFormatter, debugFilter) //#4\ndef myLog  = appender.curry(myConf, consoleAppender)        //#4\n\nmyLog('here is some debug message')\nmyLog('this will not be printed')\n//#1 Configuration use\n//#2 Formatting use\n//#3 Filter, format, and output parts\n//#4 Putting it all together\n"
  },
  {
    "path": "listings/chap05/Listing_05_09_closure_scope.groovy",
    "content": "class Mother {\n  def prop = 'prop'\n  def method(){ 'method' }\n  Closure birth (param) {                              //#1\n    def local = 'local'\n    def closure = { \n      [ this, prop, method(), local, param ]\n    }\n    return closure\n  }\n}\n\nMother julia = new Mother()\ndef closure  = julia.birth('param')                    //#2\n\ndef context  = closure.call()                          //#3\n\nassert context[0]    == julia                          //#4\nassert context[1, 2] == ['prop',  'method']            //#5\nassert context[3, 4] == ['local', 'param' ]            //#6\n\nassert closure.thisObject == julia                     //|#7\nassert closure.owner      == julia                     //|#7\n\nassert closure.delegate   == julia                     //|#8\nassert closure.resolveStrategy == Closure.OWNER_FIRST  //|#8\n\n\n//#1 Creation method\n//#2 Closure declaration time\n//#3 Closure execution time\n//#4 What \"this\" refers to\n//#5 Free variables, resolved\n//#6 Bound variables\n//#7 Read only\n//#8 Scope control"
  },
  {
    "path": "listings/chap05/Listing_05_10_closure_accumulator.groovy",
    "content": "def foo(n) {\n    return { n += it }\n}\n\ndef accumulator = foo(1)\nassert accumulator(2) == 3\nassert accumulator(1) == 4"
  },
  {
    "path": "listings/chap05/Listing_05_11_visitor_pattern.groovy",
    "content": "class Drawing {\n    List shapes\n    def accept(Closure yield) { shapes.each{it.accept(yield)} }\n}\nclass Shape {\n    def accept(Closure yield) { yield(this) }\n}\nclass Square extends Shape {\n    def width\n    def area() { width**2 }\n}\nclass Circle extends Shape {\n    def radius\n    def area() { Math.PI * radius**2 }\n}\n\ndef picture = new Drawing(shapes: [new Square(width:1), new Circle(radius:1)])\n\ndef total = 0\npicture.accept { total += it.area() }\nprintln \"The shapes in this drawing cover an area of $total units.\"\nprintln 'The individual contributions are: '\npicture.accept { println it.class.name + \":\" + it.area() }"
  },
  {
    "path": "listings/chap05/extra_ClosureProperty.groovy",
    "content": "class GrailsController {\n    def params = [a:1, b:2]\n    def list   = { params.keySet().toList() }\n}\n\ndef controller = new GrailsController()\nassert controller.list() == ['a', 'b']\n\ncontroller.list = { controller.params.values().toList() }\nassert controller.list() == [1, 2]"
  },
  {
    "path": "listings/chap05/extra_Closure_delegate.groovy",
    "content": "def list = []\ndef expected = [1, 2]\n\nlist.with {\n    add 1\n    add 2\n    assert delegate == expected\n}"
  },
  {
    "path": "listings/chap05/extra_Closure_myWith.groovy",
    "content": "def with(Closure doit) {  // fake implementation\n    doit.delegate = list\n    doit()\n}"
  },
  {
    "path": "listings/chap05/snippet0501_envelope.groovy.txt",
    "content": "Closure envelope = { person -> new Letter(person).send() }\naddressBook.each (envelope)\n"
  },
  {
    "path": "listings/chap05/snippet0504_closure_default_params.groovy",
    "content": "def adder = { x, y=5 -> return x+y }\n\nassert adder(4, 3) == 7   \nassert adder.call(7) == 12\n"
  },
  {
    "path": "listings/chap05/snippet0504_closure_isCase.groovy",
    "content": "def odd = { it % 2 == 1}\n\nassert [1,2,3].grep(odd) == [1, 3]\n\nswitch(10) {\n    case odd : assert false\n}\n\nif (2 in odd) assert false\n"
  },
  {
    "path": "listings/chap05/snippet0504_closure_paramcount.groovy",
    "content": "def numParams (Closure closure){\n  closure.getMaximumNumberOfParameters()\n}\n\nassert numParams { one -> }      == 1\nassert numParams { one, two -> } == 2\n\ndef paramTypes (Closure closure){\n  closure.getParameterTypes()\n}\n\nassert paramTypes { String s -> } == [String]\nassert paramTypes { Number n, Date d -> } == [Number, Date]\n"
  },
  {
    "path": "listings/chap05/snippet0505_map_with.groovy",
    "content": "def map = [:]\nmap.with {\n    a = 1\n    b = 2    \n} \nassert map == [a:1, b:2]"
  },
  {
    "path": "listings/chap05/snippet0505_scoping.groovy",
    "content": "def x = 0\n10.times {\n  x++\n}\nassert x == 10\n"
  },
  {
    "path": "listings/chap05/snippet0506_closure_return.groovy",
    "content": "assert [2, 4, 6] == [1, 2, 3].collect { it * 2 }\n\nassert [2, 4, 6] == [1, 2, 3].collect { return it * 2 }\n\nassert [1, 4, 3] == [1, 2, 3].collect {\n  if (it % 2 == 0) return it * 2\n  return it\n}\n"
  },
  {
    "path": "listings/chap05/snippet0507_closure_composition.groovy",
    "content": "def mult  = { x, y -> return x * y }\ndef twoTimes = mult.curry(2)\nassert twoTimes(5) == 10\n\ndef fourTimes  = twoTimes >> twoTimes\ndef eightTimes = twoTimes << fourTimes\n\nassert eightTimes(1) == twoTimes(fourTimes(1))"
  },
  {
    "path": "listings/chap05/snippet0508_memoize.groovy",
    "content": "def fib \nfib = { it < 2 ? 1 : fib(it-1) + fib(it-2) }\nfib = fib.memoize()\n\nassert fib(40) == 165_580_141\n\n\n// nano time\n// without memoize 22_903_497_000\n// with memoize         1_074_000"
  },
  {
    "path": "listings/chap05/snippet0509_trampoline.groovy",
    "content": "def last\nlast = { it.size() == 1 ? it.head() : last.trampoline(it.tail()) }\n\nlast = last.trampoline()\n\nassert last(0..10_000) == 10_000"
  },
  {
    "path": "listings/chap06/Listing_06_01_groovy_truth.groovy",
    "content": "assert true                                            //#A\nassert !false                                          //#A\n\nassert ('a' =~ /./)                                    //#B\nassert !('a' =~ /b/)                                   //#B\n\nassert [1]                                             //#C\nassert ![]                                             //#C\n\nIterator iter = [1].iterator()\nassert iter                                            //#D\niter.next()                                            //#D\nassert !iter                                           //#D\n\nassert ['a':1]                                         //#E\nassert ![:]                                            //#E\n\nassert 'a'                                             //#F\nassert !''                                             //#F\n\nassert 1                                               //#G\nassert 1.1                                             //#G\nassert 1.2f                                            //#G\nassert 1.3g                                            //#G\nassert 2L                                              //#G\nassert 3G                                              //#G\nassert !0                                              //#G\n\nassert ! null                                          //#H\nassert new Object()                                    //#H\n\nclass AlwaysFalse {\n    boolean asBoolean() { false }                      //#I\n}\nassert ! new AlwaysFalse()                             //#J\n//#A Boolean values are trivial\n//#B Matchers must match\n//#C Collections must be nonempty\n//#D Iterators must have next element\n//#E Maps must be nonempty\n//#F Strings must be nonempty\n//#G Numbers (any type) must be nonzero\n//#H Objects must be non-null\n//#I Custom truth\n//#J Calls asBoolean()\n"
  },
  {
    "path": "listings/chap06/Listing_06_02_assignment_bug.groovy",
    "content": "def x = 1\n\nif (x == 2) {                                          //#1\n    assert false\n}\n/*******************\nif (x =  2) {                                          //#2\n   println x\n}\n********************/\nif ((x = 3)) {                                         //#3\n    println x \n}\nassert x == 3\n\ndef store = []\nwhile (x = x - 1) {                                    //#4\n    store << x\n}\nassert store == [2, 1]\n\nwhile (x =  2) {                                       //#5\n    println x\n    break\n}\n//#1 Normal comparison\n//#2 Not allowed; compiler error\n//#3 Assign and test in nested expression\n//#4 Deliberate assign and test in while\n//#5 Ouch—this will print 2\n"
  },
  {
    "path": "listings/chap06/Listing_06_03_if_then_else.groovy",
    "content": "if (true)       assert true\nelse            assert false\n\nif (1) {\n    assert true\n} else {\n    assert false\n}    \n\nif ('nonempty') assert true\nelse if (['x']) assert false\nelse            assert false\n\nif (0)          assert false\nelse if ([])    assert false\nelse            assert true\n"
  },
  {
    "path": "listings/chap06/Listing_06_04_conditional_operator.groovy",
    "content": "def result = (1==1) ? 'ok' : 'failed'\nassert result == 'ok'\n\nresult = 'some string' ? 10 : ['x']\nassert result == 10\n"
  },
  {
    "path": "listings/chap06/Listing_06_05_switch_basic.groovy",
    "content": "def a = 1\ndef log = ''\nswitch (a) {\n    case 0  : log += '0'                               //#A\n    case 1  : log += '1'                               //#A\n    case 2  : log += '2' ; break\n    default : log += 'default'\n}\nassert log == '12'\n//#A Fall through\n"
  },
  {
    "path": "listings/chap06/Listing_06_06_switch_advanced.groovy",
    "content": "switch (10) {\n    case 0          : assert false ; break\n    case 0..9       : assert false ; break\n    case [8,9,11]   : assert false ; break\n    case Float      : assert false ; break                   //#1\n    case {it%3 == 0}: assert false ; break                   //#2\n    case ~/../      : assert true  ; break                   //#3\n    default         : assert false ; break\n}\n//#1 Type case\n//#2 Closure case\n//#3 Regular expression case\n"
  },
  {
    "path": "listings/chap06/Listing_06_07_assert_host.groovy",
    "content": "def host = /\\/\\/([a-zA-Z0-9-]+(\\.[a-zA-Z0-9-])*?)(:|\\/)/        //#A\n\nassertHost 'http://a.b.c:8080/bla',     host, 'a.b.c'\nassertHost 'http://a.b.c/bla',          host, 'a.b.c'\nassertHost 'http://127.0.0.1:8080/bla', host, '127.0.0.1'\nassertHost 'http://t-online.de/bla',    host, 't-online.de'\nassertHost 'http://T-online.de/bla',    host, 'T-online.de'\n\ndef assertHost (candidate, regex, expected){\n    candidate.eachMatch(regex){ assert it[1] == expected }\n}\n\n// ... use host regex ...                                       //#B\n//#A Regular expression matching host\n//#B Trailing code goes here\n"
  },
  {
    "path": "listings/chap06/Listing_06_08_while.groovy",
    "content": "def list = [1, 2, 3]\nwhile (list) {\n    list.remove(0)\n}\nassert list == []\n\nwhile (list.size() < 3) list << list.size() + 1\nassert list == [1, 2, 3]"
  },
  {
    "path": "listings/chap06/Listing_06_09_for.groovy",
    "content": "def store = ''                                         //#1\nfor (String s in 'a'..'c') store += s                  //#1\nassert store == 'abc'                                  //#1\n\nstore = ''                                             //#2\nfor (i in [1, 2, 3]) {                                 //#2\n    store += i                                         //#2\n}                                                      //#2\nassert store == '123'                                  //#2\n\ndef myString = 'Old school Java'                       //#3\nstore = ''                                             //#3\nfor (int i=0; i < myString.size(); i++) {              //#3\n    store += myString[i]                               //#3\n}                                                      //#3\nassert store == myString                               //#3\n\nmyString = 'Java range index'                          //#4\nstore = ''                                             //#4\nfor (int i : 0 ..< myString.size()) {                  //#4\n    store += myString[i]                               //#4\n}                                                      //#4\nassert store == myString                               //#4\n\nmyString = 'Groovy range index'                        //#5\nstore = ''                                             //#5\nfor (i in 0 ..< myString.size()) {                     //#5\n    store += myString[i]                               //#5\n}                                                      //#5\nassert store == myString                               //#5\n\nmyString = 'Java string Iterable'                      //#6\nstore = ''                                             //#6\nfor (String s : myString) {                            //#6\n    store += s                                         //#6\n}                                                      //#6\nassert store == myString                               //#6\n\nmyString = 'Groovy iterator'                           //#7\nstore = ''                                             //#7\nfor (s in myString) {                                  //#7\n    store += s                                         //#7\n}                                                      //#7\nassert store == myString                               //#7\n//#1 Explicit typing, over string range, no braces\n//#2 Implicit typing, over list as collection, braces\n//#3 Explicit typing, Java-style traditional for loop, braces\n//#4 Explicit typing, Java-style iterable index, braces\n//#5 Implicit typing, over half-exclusive IntRange, braces\n//#6 Explicit typing, Java-style iterable value, braces\n//#7 Implicit typing, over string as collection, braces\n"
  },
  {
    "path": "listings/chap06/Listing_06_10_break_continue.groovy",
    "content": "def a = 1\nwhile (true) {                                         //#A\n    a++\n    break                                              //#B\n}\nassert a == 2\n\nfor (i in 0..10) {\n    if (i==0)  continue                                //#C\n    a++\n    if (i > 0) break                                   //#D\n}\nassert a==3\n//#A Do forever\n//#B Forever is over now\n//#C Proceed with 1\n//#D Premature loop end\n"
  },
  {
    "path": "listings/chap06/Listing_06_11_exception_example.groovy",
    "content": "def myMethod() {\n    throw new IllegalArgumentException()\n}\n\ndef log = []\ntry {\n    myMethod()\n} catch (Exception e) {\n    log << e.toString()\n} finally {\n    log << 'finally'\n}\nassert log.size() == 2"
  },
  {
    "path": "listings/chap06/extra_if_return.groovy",
    "content": "def mac() {\n    if (System.properties.'os.name'.contains('Mac'))\n        \"We're on Mac.\" // no 'return'\n    else\n        \"Oh, well ...\"  // no 'return'\n}\nprintln mac()"
  },
  {
    "path": "listings/chap06/extra_in_operator.groovy",
    "content": "assert 1 in [0, 1, 2]       // list\nassert 1 in 0..3            // range\nassert 'Hello' in String    // class\nassert 'Hello' in ~/H.*/    // pattern"
  },
  {
    "path": "listings/chap06/extra_switch_return.groovy",
    "content": "def mac() {\n    switch(System.properties.'os.name') {\n        case 'Mac OS X': \"We're on Mac.\"; break // no 'return'\n        default:         \"Oh, well ...\"         // no 'return'\n    }   \n}\nprintln mac()"
  },
  {
    "path": "listings/chap06/myFileName.txt",
    "content": "line one\nline two"
  },
  {
    "path": "listings/chap06/snippet0602_bad_file_read.groovy",
    "content": "try {\n    input = new File('no such file')\n    assert input.exists()\n    assert input.canRead()\n    println input.text\n} catch (AssertionError error) {\n    assert \"\\n\" + error.message == '''\nassert input.exists()\n       |     |\n       |     false\n       no such file'''\n}"
  },
  {
    "path": "listings/chap06/snippet0602_bad_file_read_with_message.groovy",
    "content": "try {\n    input = new File('/no such file')\n    assert input.exists(), \"cannot find: $input.canonicalPath\"\n    assert input.canRead()\n    println input.text\n} catch (AssertionError error) {\n    def root = new File('/').canonicalPath\n    assert error.message ==\n        'cannot find: ' + root + 'no such file. ' +\n        'Expression: input.exists()'\n}\n"
  },
  {
    "path": "listings/chap06/snippet0602_failing_assert.groovy",
    "content": "def a = 1\ntry {\n    assert a == 2\n} catch (AssertionError error) {\n    assert \"\\n\" + error.message =='''\nassert a == 2\n       | |\n       1 false'''\n}"
  },
  {
    "path": "listings/chap06/snippet0603_each_loop_iterate.groovy",
    "content": "(0..9).each { println it }\n"
  },
  {
    "path": "listings/chap06/snippet0603_file_iterate_lines.groovy",
    "content": "def file = new File('myFileName.txt')\nfor (line in file) println line\n"
  },
  {
    "path": "listings/chap06/snippet0603_for_loop_iterate.groovy",
    "content": "for (x in 0..9) { println x }\n"
  },
  {
    "path": "listings/chap06/snippet0603_null_iterate.groovy",
    "content": "for (x in null) println 'This will not be printed!'\n"
  },
  {
    "path": "listings/chap06/snippet0603_object_iterate.groovy",
    "content": "for (x in new Object()) println \"Printed once for object $x\"\n"
  },
  {
    "path": "listings/chap06/snippet0603_regex_iterate_match.groovy",
    "content": "def matcher = '12xy3'=~/\\d/\nfor (match in matcher) println match\n"
  },
  {
    "path": "listings/chap06/snippet0604_multicatch.groovy",
    "content": "try {\n  if (Math.random() < 0.5) 1 / 0\n  else null.hashCode()\n} catch (ArithmeticException | NullPointerException exception) {\n  println exception.class.name\n}\n"
  },
  {
    "path": "listings/chap07/Listing_07_01_Declaring_Variables.groovy",
    "content": "class ClassWithTypedAndUntypedFieldsAndProperties {\n\n    public    fieldWithModifier\n    String    typedField\n    def       untypedField\n    protected field1, field2, field3\n    private   assignedField = new Date()\n\n    static    classField\n    public static final String CONSTA = 'a', CONSTB = 'b'\n\n    def someMethod(){\n        def localUntypedMethodVar = 1\n        int localTypedMethodVar = 1\n        def localVarWithoutAssignment, andAnotherOne\n    }\n}\n\ndef localvar = 1                                       //#A\nboundvar1 = 1                                          //#B\n\ndef someMethod(){                                      //#C\n    def localMethodVar = 1                             //#C\n    boundvar2 = 1                                      //#C\n}                                                      //#C\nsomeMethod()\n//#A Local variable to the script\n//#B From the binding\n//#C Local method to the script\n"
  },
  {
    "path": "listings/chap07/Listing_07_02_TypeBreaking_Assignment.groovy",
    "content": "final String PI = '3.14'\nassert PI.class.name == 'java.lang.String'\nassert PI.size() == 4\nGroovyAssert.shouldFail(ClassCastException){\n    Float areaOfCircleRadiusOne = PI\n}"
  },
  {
    "path": "listings/chap07/Listing_07_03_Referencing_Fields.groovy",
    "content": "class Counter {\n    public count = 0\n}\n\ndef counter = new Counter()\n\ncounter.count = 1\nassert counter.count == 1\n\ndef fieldName = 'count'\ncounter[fieldName] = 2\nassert counter['count'] == 2"
  },
  {
    "path": "listings/chap07/Listing_07_04_Overriding_Field_Access.groovy",
    "content": "class PretendFieldCounter {\n    public count = 0\n\n    Object get (String name) {\n        return 'pretend value'\n    }\n    void set (String name, Object value) {\n        count++\n    }\n}\n\ndef pretender = new PretendFieldCounter()\n\nassert pretender.isNoField == 'pretend value'\nassert pretender.count     == 0\n\npretender.isNoFieldEither  = 'just to increase counter'\n\nassert pretender.count     == 1"
  },
  {
    "path": "listings/chap07/Listing_07_05_Declaring_Methods.groovy",
    "content": "class ClassWithTypedAndUntypedMethods {\n\n  static void main(args) {                             //#1\n    def some = new ClassWithTypedAndUntypedMethods()\n    some.publicVoidMethod()\n    assert 'hi' == some.publicUntypedMethod()\n    assert 'ho' == some.publicTypedMethod()\n    combinedMethod()                                   //#A\n  }\n\n  void publicVoidMethod() { }\n\n  def publicUntypedMethod() {\n    return 'hi'\n  }\n\n  String publicTypedMethod() {\n    return 'ho'\n  }\n\n  private static final void combinedMethod() { }\n}\n//#1 Implicit public\n//#A Call static method of current class\n"
  },
  {
    "path": "listings/chap07/Listing_07_06_Declaring_Parameters.groovy",
    "content": "class ClassWithTypedAndUntypedMethodParams {\n  static void main(args) {\n    assert 'untyped' == method(1)\n    assert 'typed' == method('whatever')\n    assert 'two args' == method(1, 2)\n  }\n\n  static method(arg) {\n    return 'untyped'\n  }\n\n  static method(String arg) {\n    return 'typed'\n  }\n\n  static method(arg1, Number arg2) {\n    return 'two args'\n  }\n}"
  },
  {
    "path": "listings/chap07/Listing_07_07_Parameter_Usages.groovy",
    "content": "class Summer {\n    def sumWithDefaults(a, b, c=0){                       //#1\n        return a + b + c\n    }\n    def sumWithList(List args){                           //#2\n        return args.inject(0){sum,i -> sum += i}\n    }\n    def sumWithOptionals(a, b, Object[] optionals){       //#3\n        return a + b + sumWithList(optionals.toList())\n    }\n    def sumNamed(Map args){                               //#4\n        ['a','b','c'].each{args.get(it,0)}\n        return args.a + args.b + args.c\n    }\n}\n\ndef summer = new Summer()\n\nassert 2 == summer.sumWithDefaults(1,1)\nassert 3 == summer.sumWithDefaults(1,1,1)\n\nassert 2 == summer.sumWithList([1,1])\nassert 3 == summer.sumWithList([1,1,1])\n\nassert 2 == summer.sumWithOptionals(1,1)\nassert 3 == summer.sumWithOptionals(1,1,1)\n\nassert 2 == summer.sumNamed(a:1, b:1)\nassert 3 == summer.sumNamed(a:1, b:1, c:1)\nassert 1 == summer.sumNamed(c:1)\n//#1 Explicit arguments and a default value\n//#2 Define arguments as a list\n//#3 Optional arguments as an array\n//#4 Define arguments as a map\n"
  },
  {
    "path": "listings/chap07/Listing_07_08_Safe_Dereferencing.groovy",
    "content": "def map = [a:[b:[c:1]]]           \n\nassert map.a.b.c == 1\n\nif (map && map.a && map.a.x){                          //#1\n    assert map.a.x.c == null\n}\n\ntry {\n    assert map.a.x.c == null\n} catch (NullPointerException ignore){                 //#2\n}\n\nassert map?.a?.x?.c == null                            //#3\n//#1 Protect with if: short-circuit evaluation\n//#2 Protect with try/catch\n//#3 Safe dereferencing\n"
  },
  {
    "path": "listings/chap07/Listing_07_09_Instantiation.groovy",
    "content": "class VendorWithCtor {\n    String name, product\n\n    VendorWithCtor(name, product) {                    //#A\n        this.name    = name\n        this.product = product\n    }\n}\n\ndef first = new VendorWithCtor('Canoo','ULC')          //#B\n\ndef second = ['Canoo','ULC'] as VendorWithCtor         //#1\n\nVendorWithCtor third = ['Canoo','ULC']                 //#2\n//#A Constructor definition\n//#B Normal constructor use\n//#1 Coercion with as\n//#2 Coercion in assignment\n"
  },
  {
    "path": "listings/chap07/Listing_07_10_Instantiation_Named.groovy",
    "content": "class SimpleVendor {\n    String name, product\n}\n\nnew SimpleVendor()\nnew SimpleVendor(name: 'Canoo')\nnew SimpleVendor(product: 'ULC')\nnew SimpleVendor(name: 'Canoo', product: 'ULC')\n\ndef vendor = new SimpleVendor(name: 'Canoo')\nassert 'Canoo' == vendor.name\n"
  },
  {
    "path": "listings/chap07/Listing_07_11_Classes.groovy",
    "content": "class Vendor {\n    public String     name\n    public String     product\n    public Address    address = new Address()\n}\n\nclass Address  {\n    public String     street, town, state\n    public int        zip\n}\n\ndef canoo = new Vendor()\ncanoo.name            = 'Canoo Engineering AG'\ncanoo.product         = 'UltraLightClient (ULC)'\ncanoo.address.street  = 'Kirschgartenst. 7'\ncanoo.address.zip     =  4051\ncanoo.address.town    = 'Basel'\ncanoo.address.state   = 'Switzerland'\n\nassert canoo.dump()         =~ /ULC/\nassert canoo.address.dump() =~ /Basel/"
  },
  {
    "path": "listings/chap07/Listing_07_13_Import.groovy",
    "content": "import business.*\n\ndef canoo = new Vendor()\ncanoo.name          = 'Canoo Engineering AG'\ncanoo.product       = 'UltraLightClient (ULC)'\n\nassert canoo.dump() =~ /ULC/"
  },
  {
    "path": "listings/chap07/Listing_07_14_Import_As_BugFix.groovy",
    "content": "import thirdparty.MathLib as OrigMathLib\n\nclass MathLib extends OrigMathLib {\n    Integer twice(Integer value) {\n        return value * 2\n    }\n}\n\n// nothing changes below here                          //#A\ndef mathlib = new MathLib()\n\nassert 10 == mathlib.twice(5)                          //#B\nassert 2 == mathlib.half(5)                            //#C\n//#A Usage code for library remains unchanged\n//#B Invoke fixed method\n//#C Invoke original method\n"
  },
  {
    "path": "listings/chap07/Listing_07_15_Import_As_NameClash.groovy",
    "content": "import thirdparty.MathLib as TwiceHalfMathLib\nimport thirdparty2.MathLib as IncMathLib\n\ndef math1 = new TwiceHalfMathLib()\ndef math2 = new IncMathLib()\n\nassert 3 == math1.half(math2.increment(5))"
  },
  {
    "path": "listings/chap07/Listing_07_16_Multimethods.groovy",
    "content": "def oracle(Object o) { return 'object' }\ndef oracle(String o) { return 'string' }\n\nObject x = 1\nObject y = 'foo'\n\nassert 'object' == oracle(x)\nassert 'string' == oracle(y)                           //#A\n//#A This would return object in Java\n"
  },
  {
    "path": "listings/chap07/Listing_07_17_MultiEquals.groovy",
    "content": "class Equalizer {\n    boolean equals(Equalizer e){\n        return true\n    }\n}\n\nObject same  = new Equalizer()\nObject other = new Object()\n\nassert   new Equalizer().equals( same  )\nassert ! new Equalizer().equals( other )"
  },
  {
    "path": "listings/chap07/Listing_07_18_Traits.groovy",
    "content": "trait HasId { //#1\n  long id\n}\ntrait HasVersion {\n  long version\n}\ntrait Persistent {\n  boolean save() { println \"saving ${this.dump()}\" }\n}\ntrait Entity implements Persistent, HasId, HasVersion { //#2\n  boolean save() {\n    version++\n    Persistent.super.save() //#3\n  }\n}\n\nclass Publication implements Entity { //#4\n  String title\n}\n\nclass Book extends Publication {\n  String isbn\n}\n\nEntity gina = new Book(id:1, version:1, title:\"gina\", isbn:\"111111\")\ngina.save()\nassert gina.version == 2\n//#1 Defining a trait with state\n//#2 Traits can use subtyping\n//#3 Use specific methods\n//#4 Implementing the trait\n"
  },
  {
    "path": "listings/chap07/Listing_07_19_Declaring_Beans.groovy",
    "content": "import java.io.Serializable\n\nclass MyBean implements Serializable {\n    def untyped\n    String typed\n    def item1, item2\n    def assigned = 'default value'\n}\n\ndef bean = new MyBean()\nassert 'default value' == bean.getAssigned()\nbean.setUntyped('some value')\nassert 'some value' == bean.getUntyped()\nbean = new MyBean(typed:'another value')\nassert 'another value' == bean.getTyped()"
  },
  {
    "path": "listings/chap07/Listing_07_20_Calling_Beans.groovy",
    "content": "class MrBean {\n    String firstname, lastname                         //#A\n    \n    String getName(){                                  //#1\n        return \"$firstname $lastname\"\n    }\n}\n\ndef bean = new MrBean(firstname: 'Rowan')              //#B\nbean.lastname = 'Atkinson'                             //#2\n\nassert 'Rowan Atkinson' == bean.name                   //#3\n//#A Groovy style properties\n//#1 Getter for derived property\n//#B Generic constructor\n//#2 Call setter\n//#3 Call getter\n"
  },
  {
    "path": "listings/chap07/Listing_07_21_Calling_Beans_Advanced.groovy",
    "content": "class DoublerBean {\n    public value                                       //#A\n    \n    void setValue(value){\n        this.value = value                             //#1\n    }\n    \n    def getValue(){                        \n        value * 2                                      //#2\n    }\n}\n\ndef bean = new DoublerBean(value: 100)     \n\nassert 200 == bean.value                               //#3\nassert 100 == bean.@value                              //#B\n//#A Visible field\n//#1 Inner field access\n//#2 Inner field access\n//#3 Property access\n//#B Outer field access\n"
  },
  {
    "path": "listings/chap07/Listing_07_22_Property_Methods.groovy",
    "content": "class ClassWithProperties {\n    def       someProperty\n    public    someField\n    private   somePrivateField\n}\n\ndef obj = new ClassWithProperties()\n\ndef store = []\nobj.properties.each { property ->\n    store += property.key\n    store += property.value\n}\nassert store.contains('someProperty')\nassert store.contains('someField')        == false \nassert store.contains('somePrivateField') == false\nassert store.contains('class')\n\nassert obj.properties.size() == 2"
  },
  {
    "path": "listings/chap07/Listing_07_23_Expando.groovy",
    "content": "def boxer = new Expando()\n\nassert null == boxer.takeThis\n\nboxer.takeThis = 'ouch!'\n\nassert 'ouch!' == boxer.takeThis\n\nboxer.fightBack = {times -> delegate.takeThis * times  }\n\nassert 'ouch!ouch!ouch!' == boxer.fightBack(3)\n"
  },
  {
    "path": "listings/chap07/Listing_07_24_GPath.groovy",
    "content": "class Invoice {                                          //#A\n    List    items                                        //#A\n    Date    date                                         //#A\n}                                                        //#A\nclass LineItem {                                         //#A\n    Product product                                      //#A\n    int     count                                        //#A\n    int total() {                                        //#A\n        return product.dollar * count                    //#A\n    }                                                    //#A\n}                                                        //#A\nclass Product {                                          //#A\n    String  name                                         //#A\n    def     dollar                                       //#A\n}                                                        //#A\n\ndef ulcDate = Date.parse('yyyy-MM-dd', '2015-01-01')\ndef otherDate = Date.parse('yyyy-MM-dd', '2015-02-02')\ndef ulc = new Product(dollar:1499, name:'ULC')           //#B\ndef ve  = new Product(dollar:499,  name:'Visual Editor') //#B\n                                                         //#B\ndef invoices = [                                         //#B\n    new Invoice(date:ulcDate, items: [                   //#B\n        new LineItem(count:5, product:ulc),              //#B\n        new LineItem(count:1, product:ve)                //#B\n    ]),                                                  //#B\n    new Invoice(date:otherDate, items: [                 //#B\n        new LineItem(count:4, product:ve)                //#B\n    ])                                                   //#B\n]                                                        //#B\n\ndef allItems = invoices.items.flatten()\n\nassert [5*1499, 499, 4*499] == allItems*.total()                 //#1\n\nassert ['ULC'] == allItems.grep{it.total() > 7000}.product.name  //#2\n\ndef searchDates = invoices.grep{                         //#3\n    it.items.any{it.product == ulc}                      //#3\n}.date*.toString()                                       //#3\nassert [ulcDate.toString()] == searchDates\n//#A Set up data structures\n//#B Fill with sample data\n//#1 Total for each line item\n//#2 Query of product names\n//#3 Query of invoice date\n"
  },
  {
    "path": "listings/chap07/business/Vendor.groovy",
    "content": "package business\n\nclass Vendor {\n    public String  name\n    public String  product\n    public Address address = new Address()\n}\n\nclass Address  {\n    public String  street, town, state\n    public int     zip\n}"
  },
  {
    "path": "listings/chap07/snippet0703_Implicit_Closure_To_SAM.groovy",
    "content": "import java.awt.event.ActionListener\nlisteners = []\ndef addListener(ActionListener al) { listeners << al }\naddListener { println \"I heard that!\" }\nlisteners*.actionPerformed()\n"
  },
  {
    "path": "listings/chap07/snippet0705_Spread_List.groovy",
    "content": "def getList(){\n    return [1,2,3]\n}\ndef sum(a,b,c){\n    return a + b + c\n}\nassert 6 == sum(*list)"
  },
  {
    "path": "listings/chap07/snippet0705_Spread_Map.groovy",
    "content": "def map = [a:1,b:2]\nassert [a:1, b:2, c:3] == [c:3, *:map]"
  },
  {
    "path": "listings/chap07/snippet0705_Spread_Range.groovy",
    "content": "def range = (1..3)\nassert [0,1,2,3] == [0,*range]"
  },
  {
    "path": "listings/chap07/thirdparty/MathLib.groovy",
    "content": "package thirdparty\n\nclass MathLib {\n  Integer twice(Integer value) {\n    return value * 3         // intentionally wrong!\n  }\n  Integer half(Integer value) {\n    return value / 2\n  }\n}\n"
  },
  {
    "path": "listings/chap07/thirdparty2/MathLib.groovy",
    "content": "package thirdparty2\n\nclass MathLib {\n  Integer increment(Integer value) { value + 1 }\n}\n"
  },
  {
    "path": "listings/chap08/Listing_08_01_method_missing.groovy",
    "content": "class Pretender {\n    def methodMissing(String name, Object args) {\n        \"called $name with $args\"\n    }\n}\ndef bounce = new Pretender()\nassert bounce.hello('world') == 'called hello with [world]'"
  },
  {
    "path": "listings/chap08/Listing_08_02_mini_gorm.groovy",
    "content": "class MiniGorm {\n    def db = []\n    Object methodMissing(String name, Object args) {\n        println name\n        db.find { it[name.toLowerCase()-'findby'] == args[0] } //#1\n    }\n}\n\ndef people = new MiniGorm()                         //#2\ndef dierk  = [first: 'Dierk', last:'Koenig']\ndef paul   = [first: 'Paul',  last:'King']\npeople.db << dierk << paul\n\nassert people.findByFirst('Dierk') == dierk         //#3\nassert people.findByLast('King')   == paul"
  },
  {
    "path": "listings/chap08/Listing_08_03_property_missing.groovy",
    "content": "class PropPretender {\n    def propertyMissing(String name) {\n        \"accessed $name\"\n    }\n}\ndef bounce = new PropPretender()\nassert bounce.hello == 'accessed hello'"
  },
  {
    "path": "listings/chap08/Listing_08_04_bin_property.groovy",
    "content": "def propertyMissing(String name) {\n    int result = 0\n    name.each {\n        result <<= 1\n        if (it == 'I') result++\n    }\n    return result\n}\n\nassert IIOI +\n        IOI ==\n      IOOIO\n"
  },
  {
    "path": "listings/chap08/Listing_08_05_closure_dynamic.groovy",
    "content": "class DynamicPretender {\n    Closure whatToDo = { name -> \"accessed $name\"}  //#1\n    def propertyMissing(String name) {\n        whatToDo(name)                              //#2\n    }\n}\ndef one = new DynamicPretender()\nassert one.hello == 'accessed hello'\none.whatToDo     = { name -> name.size() }          //#3\nassert one.hello == 5"
  },
  {
    "path": "listings/chap08/Listing_08_06_property_method.groovy",
    "content": "class NoParens {\n    def getProperty(String propertyName) {\n        if (metaClass.hasProperty(this, propertyName)) { //#1\n            return metaClass.getProperty(this, propertyName)\n        }\n       invokeMethod propertyName, null  //#2\n    }\n}\n\nclass PropUser extends NoParens {       //#3\n    boolean existingProperty = true\n}\n\ndef user = new PropUser()\nassert user.existingProperty\nassert user.toString() == user.toString //#4"
  },
  {
    "path": "listings/chap08/Listing_08_07_MetaClass_jdk7_only.groovy",
    "content": "MetaClass mc = String.metaClass\nfinal Object[] NO_ARGS = []\nassert   1  == mc.respondsTo(\"toString\", NO_ARGS).size()\nassert   3  == mc.properties.size()\nassert  74  == mc.methods.size()\nassert 176  == mc.metaMethods.size()\nassert \"\"   == mc.invokeMethod(\"\",\"toString\", NO_ARGS)\nassert null == mc.invokeStaticMethod(String, \"println\", NO_ARGS)\nassert \"\"   == mc.invokeConstructor(NO_ARGS)"
  },
  {
    "path": "listings/chap08/Listing_08_07_MetaClass_jdk8_plus.groovy",
    "content": "MetaClass mc = String.metaClass\nfinal Object[] NO_ARGS = []\nassert   1  == mc.respondsTo(\"toString\", NO_ARGS).size()\nassert   3  == mc.properties.size()\nassert  76  == mc.methods.size()\nassert 176  == mc.metaMethods.size()\nassert \"\"   == mc.invokeMethod(\"\",\"toString\", NO_ARGS)\nassert null == mc.invokeStaticMethod(String, \"println\", NO_ARGS)\nassert \"\"   == mc.invokeConstructor(NO_ARGS)"
  },
  {
    "path": "listings/chap08/Listing_08_08_ProxyMetaClass.groovy",
    "content": "class InspectMe {\n    int outer(){\n        return inner()        \n    }\n    private int inner(){\n        return 1\n    }\n}\n\ndef tracer = new TracingInterceptor(writer: new StringWriter()) //#1\ndef proxyMetaClass = ProxyMetaClass.getInstance(InspectMe)\nproxyMetaClass.interceptor = tracer\n\nInspectMe inspectMe = new InspectMe()\ninspectMe.metaClass = proxyMetaClass  //#2\n\nassert 1 == inspectMe.outer()         //#3\n\nassert \"\\n\" + tracer.writer.toString() == \"\"\"\nbefore InspectMe.outer()\n  before InspectMe.inner()\n  after  InspectMe.inner()\nafter  InspectMe.outer()\n\"\"\""
  },
  {
    "path": "listings/chap08/Listing_08_09_Expando.groovy",
    "content": "def boxer = new Expando()\n\nboxer.takeThis  = 'ouch!'\nboxer.fightBack = { times -> takeThis * times  }\n\nassert boxer.fightBack(3) == 'ouch!ouch!ouch!'"
  },
  {
    "path": "listings/chap08/Listing_08_10_EMC.groovy",
    "content": "assert String.metaClass =~ /MetaClassImpl/\nString.metaClass.low    = {-> delegate.toLowerCase() }\nassert String.metaClass =~ /ExpandoMetaClass/\n\nassert \"DiErK\".low() == \"dierk\""
  },
  {
    "path": "listings/chap08/Listing_08_11_EMC_Groovy_Class.groovy",
    "content": "class MyGroovy1 { }\n\ndef before = new MyGroovy1()\n\nMyGroovy1.metaClass.myProp = \"MyGroovy prop\"\nMyGroovy1.metaClass.test = {-> myProp }\n\ntry {\n    before.test()                   //#1\n    assert false, \"should throw MME\"\n} catch(mme) { }\n\nassert new MyGroovy1().test() == \"MyGroovy prop\""
  },
  {
    "path": "listings/chap08/Listing_08_12_EMC_Groovy_Object.groovy",
    "content": "class MyGroovy2 { }\n\ndef myGroovy = new MyGroovy2()\n\nmyGroovy.metaClass.myProp = \"MyGroovy prop\"\nmyGroovy.metaClass.test = {-> myProp }\n\ntry {\n    new MyGroovy2().test()          //#1\n    assert false, \"should throw MME\"\n} catch(mme) { }\n\nassert myGroovy.test() == \"MyGroovy prop\""
  },
  {
    "path": "listings/chap08/Listing_08_13_EMC_Java_Object.groovy",
    "content": "def myJava = new String()\n\nmyJava.metaClass.myProp = \"MyJava prop\"\nmyJava.metaClass.test = {-> myProp }\n\ntry {\n    new String().test()             //#1\n    assert false, \"should throw MME\"\n} catch(mme) { }\n\nassert myJava.test() == \"MyJava prop\""
  },
  {
    "path": "listings/chap08/Listing_08_14_EMC_Builder.groovy",
    "content": "def move(string, distance) {\n    string.collect { (it as char) + distance as char }.join()\n}\n\nString.metaClass {\n    shift = -1\n    encode  {-> move delegate, shift  }\n    decode  {-> move delegate, -shift }\n    getCode {-> encode() }\n    getOrig {-> decode() }\n}\n\nassert \"IBM\".encode() == \"HAL\"\nassert \"HAL\".orig     == \"IBM\"\n\ndef ibm = \"IBM\"\nibm.shift = 7\nassert ibm.code == \"PIT\""
  },
  {
    "path": "listings/chap08/Listing_08_15_EMC_static.groovy",
    "content": "Integer.metaClass.static.answer = {-> 42}\n\nassert Integer.answer() == 42"
  },
  {
    "path": "listings/chap08/Listing_08_16_EMC_super.groovy",
    "content": "class MySuperGroovy { }\nclass MySubGroovy extends MySuperGroovy { }\n\nMySuperGroovy.metaClass.added = {-> true }\n\nassert new MySubGroovy().added()\n\nMap.metaClass.toTable = {->\n    delegate.collect{ [it.key, it.value] }\n}\n\nassert [a:1, b:2].toTable() == [\n       ['a', 1],\n       ['b', 2]\n]"
  },
  {
    "path": "listings/chap08/Listing_08_17_EMC_hooks.groovy",
    "content": "String.metaClass {\n    rightShiftUnsigned = { prefix ->\n        delegate.replaceAll(~/\\w+/) { prefix + it }\n    }\n    methodMissing = { String name, args->\n        delegate.replaceAll name, args[0]\n    }\n}\n\ndef people = \"Dierk,Guillaume,Paul,Hamlet,Jon\"\npeople  >>>= \"\\n    \"\npeople     =  people.Dierk('Mittie').Guillaume('Mr.G')\n\nassert people == '''\n    Mittie,\n    Mr.G,\n    Paul,\n    Hamlet,\n    Jon'''"
  },
  {
    "path": "listings/chap08/Listing_08_18_Existing_Categories.groovy",
    "content": "import groovy.time.TimeCategory\n\ndef janFirst1970 = new Date(0)\nuse TimeCategory, {\n    Date   xmas = janFirst1970 + 1.year - 7.days\n    assert xmas.month == Calendar.DECEMBER\n    assert xmas.date  == 25\n}\n\nuse Collections, {\n    def list     = [0, 1, 2, 3]\n    list.rotate 1\n    assert list == [3, 0, 1, 2]\n}"
  },
  {
    "path": "listings/chap08/Listing_08_19_Marshal.groovy",
    "content": "class Marshal {\n    static String marshal(Integer self) {\n        self.toString()\n    }\n    static Integer unMarshal(String self) {\n        self.toInteger()\n    }\n}\n\nuse Marshal, {\n    assert   1.marshal()   == \"1\"\n    assert \"1\".unMarshal() == 1\n    [Integer.MIN_VALUE, -1, 0, Integer.MAX_VALUE].each {\n        assert it.marshal().unMarshal() == it\n    }\n}"
  },
  {
    "path": "listings/chap08/Listing_08_20_MarshalCategory.groovy",
    "content": "@Category(Integer)                                     //#1\nclass IntegerMarshal {\n  String marshal() {\n    toString()                                         //#2\n  }\n}\n\n@Category(String)\nclass StringMarshal {\n  Integer unMarshal() {\n    this.toInteger()                                   //#3\n  }\n}\n\nuse ([IntegerMarshal, StringMarshal]) {                //#4\n  assert   1.marshal()   == \"1\"\n  assert \"1\".unMarshal() == 1\n}\n//#1 Specify the type of self\n//#2 Implicit this\n//#3 Explicit this\n//#4 List variant of use\n"
  },
  {
    "path": "listings/chap08/Listing_08_21_Test_Mixin.groovy",
    "content": "@Mixin(MessageFeature)\nclass FirstTest extends GroovyTestCase {\n    void testWithMixinUsage() {\n        message = \"Called from Test\"\n        assertMessage \"Called from Test\"\n    }\n}\nclass MessageFeature {\n    def message\n    void assertMessage(String msg) {\n        assertEquals msg, message\n    }\n}"
  },
  {
    "path": "listings/chap08/Listing_08_22_Sieve_Mixin.groovy",
    "content": "class EvenSieve {\n    def getNo2() {\n        removeAll { it % 2 == 0 }\n        return this\n    }\n}\nclass MinusSieve {\n    def minus(int num) {\n        removeAll { it % num == 0 }\n        return this\n    }\n}\n\nArrayList.mixin EvenSieve, MinusSieve\n\nassert (0..10).toList().no2 - 3 - 5 == [1, 7]"
  },
  {
    "path": "listings/chap08/Listing_08_23_Millimeter.groovy",
    "content": "Number.metaClass {\n    getMm = { delegate          }\n    getCm = { delegate *  10.mm }\n    getM  = { delegate * 100.cm }\n}\n\nassert 1.m + 20.cm - 8.mm == 1.192.m"
  },
  {
    "path": "listings/chap08/Listing_08_24_create_factory.groovy",
    "content": "import java.awt.Dimension\n\nClass.metaClass.make = { Object[] args ->\n    delegate.metaClass.invokeConstructor(*args)\n}\n\nassert new HashMap()        == HashMap.make()\nassert new Integer(42)      == Integer.make(42)\nassert new Dimension(2, 3)  == Dimension.make(2, 3)"
  },
  {
    "path": "listings/chap08/Listing_08_25_fake_assign.groovy",
    "content": "interface ChannelComponent {}\nclass Producer implements ChannelComponent {\n    List<Integer> outChannel\n}\nclass Adaptor implements ChannelComponent {\n    List<Integer> inChannel\n    List<String>  outChannel\n}\nclass Printer implements ChannelComponent {\n    List<String> inChannel\n}\n\nclass WiringCategory {\n    static connections = []\n    static setInChannel(ChannelComponent self, value){ //#1\n        connections << [target:self, source:value]\n    }\n    static getOutChannel(ChannelComponent self){\n        self\n    }\n}\n\nProducer producer = new Producer()\nAdaptor  adaptor  = new Adaptor()\nPrinter  printer  = new Printer()\n\nuse WiringCategory, {\n    adaptor.inChannel = producer.outChannel //|#2\n    printer.inChannel = adaptor.outChannel  //|#2\n}\n\nassert WiringCategory.connections == [\n        [source: producer, target: adaptor],\n        [source: adaptor,  target: printer]\n]"
  },
  {
    "path": "listings/chap08/Listing_08_26_restore_emc.groovy",
    "content": "MetaClass oldMetaClass = String.metaClass           //#1\n\nMetaMethod alias = String.metaClass.metaMethods     //#2\n                   .find { it.name == 'size' }\nString.metaClass {\n    oldSize = { -> alias.invoke delegate  }\n    size    = { -> oldSize() * 2 }\n}\n\nassert \"abc\".size()    == 6\nassert \"abc\".oldSize() == 3\n\nif (oldMetaClass.is(String.metaClass)){\n    String.metaClass {                              //#3\n        size    = { -> alias.invoke delegate }\n        oldSize = { -> throw new UnsupportedOperationException() }\n    }\n} else {\n    String.metaClass = oldMetaClass                 //#4\n}\n\nassert \"abc\".size() == 3"
  },
  {
    "path": "listings/chap08/Listing_08_27_intercept_cache_invoke.groovy",
    "content": "ArrayList.metaClass.methodMissing = { String name, Object args ->\n    assert name.startsWith(\"findBy\")\n    assert args.size() == 1\n    Object.metaClass.\"$name\" = { value ->       //#1\n        delegate.find { it[name.toLowerCase()-'findby'] == value }\n    }\n    delegate.\"$name\"(args[0])                   //#2\n}\n\ndef data = [\n    [name:'moon',    au: 0.0025],\n    [name:'sun',     au: 1     ],\n    [name:'neptune', au:30     ],\n]\n\nassert data.findByName('moon')     //#3\nassert data.findByName('sun')      //#4\nassert data.findByAu(1)"
  },
  {
    "path": "listings/chap08/custom/Custom.groovy",
    "content": "package custom\n\nclass Custom {\n\n    \n}\n"
  },
  {
    "path": "listings/chap08/custom/useCustom.groovy",
    "content": "package custom\n\nassert new Custom().metaClass =~ /CustomMetaClass/\n"
  },
  {
    "path": "listings/chap08/failing_Listing_08_15_EMC_static.groovy",
    "content": "Integer.metaClass.static.answer =  42\n\nassert Integer.answer == 42 // no such property"
  },
  {
    "path": "listings/chap08/failing_Listing_08_16_EMC_super.groovy",
    "content": "ExpandoMetaClass.enableGlobally()\n\nMap.metaClass.getTable = {->\n    delegate.collect{ [it.key, it.value] }\n}\n\nassert [a:1, b:2].table == [['a', 1], ['b', 2]]"
  },
  {
    "path": "listings/chap08/groovy/runtime/metaclass/custom/CustomMetaClass.groovy",
    "content": "package groovy.runtime.metaclass.custom\n\nclass CustomMetaClass extends MetaClassImpl {\n\n    CustomMetaClass(MetaClassRegistry registry, Class theClass) {\n        super(registry, theClass)\n        println \"custom meta class is in use\"\n    }\n\n}\n"
  },
  {
    "path": "listings/chap08/markup.html",
    "content": ""
  },
  {
    "path": "listings/chap09/.gradle/2.2.1/taskArtifacts/cache.properties",
    "content": "#Sun Feb 01 17:04:25 CET 2015\n"
  },
  {
    "path": "listings/chap09/Listing_09_01_ToStringDetective.groovy",
    "content": "import groovy.transform.ToString\n\n@ToString\nclass Detective {\n  String firstName, lastName\n}\n\ndef sherlock  = new Detective(firstName: 'Sherlock', lastName: 'Holmes')\nassert sherlock .toString() == 'Detective(Sherlock, Holmes)'\n"
  },
  {
    "path": "listings/chap09/Listing_09_02_ToStringSleuth.groovy",
    "content": "import groovy.transform.ToString\n\n@ToString(includeNames = true, ignoreNulls = true)\nclass Sleuth {\n  String firstName, lastName\n}\n\ndef nancy = new Sleuth(firstName: 'Nancy', lastName: 'Drew')\nassert nancy.toString() == 'Sleuth(firstName:Nancy, lastName:Drew)'\nnancy.lastName = null\nassert nancy.toString() == 'Sleuth(firstName:Nancy)'\n"
  },
  {
    "path": "listings/chap09/Listing_09_03_EqualsAndHashCode.groovy",
    "content": "import groovy.transform.EqualsAndHashCode\n\n@EqualsAndHashCode\nclass Actor {\n    String firstName, lastName\n}\ndef magneto = new Actor(firstName:'Ian', lastName: 'McKellen')\ndef gandalf = new Actor(firstName:'Ian', lastName: 'McKellen')\nassert magneto == gandalf\n"
  },
  {
    "path": "listings/chap09/Listing_09_04_TupleConstructor.groovy",
    "content": "import groovy.transform.TupleConstructor\n\n@TupleConstructor\nclass Athlete {\n    String firstName, lastName\n}\ndef a1 = new Athlete('Michael', 'Jordan')\ndef a2 = new Athlete('Michael')\nassert a1.firstName == a2.firstName\n"
  },
  {
    "path": "listings/chap09/Listing_09_05_Lazy.groovy",
    "content": "class Resource {                                      //#1\n    private static alive = 0\n    private static used = 0\n    Resource() { alive++ }\n    def use() { used++ }\n    static stats() { \"$alive alive, $used used\" }\n}\n\nclass ResourceMain {\n    def res1 = new Resource()                         //#2\n    @Lazy res2 = new Resource()                       //#3\n    @Lazy static res3 = { new Resource() }()          //#4\n    @Lazy(soft=true) volatile Resource res4           //#5\n}\n\nnew ResourceMain().with {\n    assert Resource.stats() == '1 alive, 0 used'      //#6\n    res2.use()\n    res3.use()\n    res4.use()\n    assert Resource.stats() == '4 alive, 3 used'      //#7\n    assert res4 instanceof Resource                   //#8\n    def expected = 'res4=java.lang.ref.SoftReference'\n    assert it.dump().contains(expected)               //#9\n}\n//#1 Define Resource class with inbuilt statistics\n//#2 Declare one normal resource\n//#3 Declare one @Lazy resource\n//#4 Declare static resource\n//#5 Thread safe and compatible with garbage collection\n//#6 After ResourceMain creation just res1 is alive\n//#7 Using res2, res3, res4 creates instances lazily\n//#8 Verify res4 class\n//#9 Verify soft reference used internally\n"
  },
  {
    "path": "listings/chap09/Listing_09_06_IndexedProperty.groovy",
    "content": "import groovy.transform.IndexedProperty\n\nclass Author {\n    String name\n    @IndexedProperty List<String> books\n}\n\ndef books = ['The Mysterious Affair at Styles',\n             'The Murder at the Vicarage']\n\nnew Author(name: 'Agatha Christie', books: books).with {\n    books[0] = 'Murder on the Orient Express'            //#1\n    setBooks(0, 'Death on the Nile')                     //#2\n    assert getBooks(0) == 'Death on the Nile'            //#3\n}\n//#1 Groovy idiom for setting the first property\n//#2 JavaBean approach to setting a single element\n//#3 JavaBean approach to reading a single element\n"
  },
  {
    "path": "listings/chap09/Listing_09_07_InheritConstructors.groovy",
    "content": "import groovy.transform.InheritConstructors\n\n@InheritConstructors\nclass MyPrintWriter extends PrintWriter { }\n\ndef pw1 = new MyPrintWriter(new File('out1.txt'))      //#A\ndef pw2 = new MyPrintWriter('out2.txt', 'US-ASCII')    //#B\n[pw1, pw2].each {\n    it << 'foo'\n    it.close()\n}\nassert new File('out1.txt').text == new File('out2.txt').text\n['out1.txt', 'out2.txt'].each{ new File(it).delete() }\n//#A File file variant\n//#B String fileName, String charset variant\n"
  },
  {
    "path": "listings/chap09/Listing_09_08_Sortable.groovy",
    "content": "import groovy.transform.Sortable\n\n@Sortable(includes = 'last,initial')                   //#1\nclass Politician {\n    String first\n    Character initial\n    String last\n\n    String initials() { first[0] + initial + last[0] }\n}\n\ndef politicians = [\n    new Politician(first: 'Margaret', initial: 'H', last: 'Thatcher'),\n    new Politician(first: 'George', initial: 'W', last: 'Bush')\n]\n\ndef sorted = politicians.toSorted()                    //#2\nassert sorted*.initials() == ['GWB', 'MHT']\ndef byInitial = Politician.comparatorByInitial()       //#3\nsorted = politicians.toSorted(byInitial)               //#4\nassert sorted*.initials() == ['MHT', 'GWB']\n//#1 Sorts by last then initial\n//#2 Performs default sort\n//#3 Autogenerates comparator based on initial\n//#4 Sorts by initial\n"
  },
  {
    "path": "listings/chap09/Listing_09_09_Builder.groovy",
    "content": "import groovy.transform.builder.Builder\n\n@Builder\nclass Chemist {\n  String first\n  String last\n  int born\n}\n\ndef builder = Chemist.builder()                                 //#1\ndef c = builder.first(\"Marie\").last(\"Curie\").born(1867).build() //#2\nassert c.first == \"Marie\"\nassert c.last == \"Curie\"\nassert c.born == 1867\n//#1 Accessing a builder instance\n//#2 Fluent API style instance creation\n"
  },
  {
    "path": "listings/chap09/Listing_09_10_Canonical.groovy",
    "content": "import groovy.transform.Canonical\n\n@Canonical\nclass Inventor {\n    String firstName, lastName\n}\n\ndef i1 = new Inventor('Thomas', 'Edison')             //#A\ndef i2 = new Inventor('Thomas')\nassert i1 != i2                                       //#B\nassert i1.firstName == i2.firstName                   //#B\nassert i1.toString() == 'Inventor(Thomas, Edison)'    //#C\n//#A Automatic tuple constructor\n//#B Objects not equal despite equal firstName property\n//#C Automatic toString method\n"
  },
  {
    "path": "listings/chap09/Listing_09_11_Immutable.groovy",
    "content": "import groovy.transform.Immutable\nimport static groovy.test.GroovyAssert.shouldFail\n\n@Immutable\nclass Genius {\n    String firstName, lastName\n}\n\ndef g1 = new Genius(firstName: 'Albert', lastName: \"Einstein\")  //#1\nassert g1.toString() == 'Genius(Albert, Einstein)'              //#2\n\ndef g2 = new Genius('Leonardo', \"da Vinci\")                     //#3\nassert g2.firstName == 'Leonardo'                               //#4\nassert g1 != g2                                                 //#5\n\nshouldFail(ReadOnlyPropertyException) {\n    g2.lastName = 'DiCaprio'\n}\n//#1 Map-based constructor\n//#2 toString method\n//#3 Tuple constructor\n//#4 property getter\n//#5 appropriate equals and hashCode\n"
  },
  {
    "path": "listings/chap09/Listing_09_12_Delegate.groovy",
    "content": "class NoisySet2 {\n    @Delegate\n    Set delegate = new HashSet()\n\n    @Override\n    boolean add(item) {\n        println \"adding $item\"\n        delegate.add(item)\n    }\n\n    @Override\n    boolean addAll(Collection items) {\n        items.each { println \"adding $it\" }\n        delegate.addAll(items)\n    }\n}\n\nSet ns = new NoisySet2()\nns.add(1)\nns.addAll([2, 3])\nassert ns.size() == 3\n"
  },
  {
    "path": "listings/chap09/Listing_09_13_Singleton.groovy",
    "content": "import static groovy.test.GroovyAssert.shouldFail\n\n@Singleton class Zeus { }\n\nassert Zeus.instance\ndef ex = shouldFail(RuntimeException) { new Zeus() }\nassert ex.message ==\n        \"Can't instantiate singleton Zeus. Use Zeus.instance\"\n"
  },
  {
    "path": "listings/chap09/Listing_09_14_Memoized.groovy",
    "content": "import groovy.transform.Memoized\n\nclass Calc {\n  def log = []\n\n  @Memoized                                            //#1\n  int sum(int a, int b) {\n    log << \"$a+$b\"                                     //#2\n    a + b\n  }\n}\n\nnew Calc().with {\n  assert sum(3, 4) == 7                                //#3\n  assert sum(4, 4) == 8\n  assert sum(3, 4) == 7                                //#4\n  assert log.join(' ') == '3+4 4+4'                    //#5\n}\n//#1 Enable memoization by annotating a method\n//#2 Log all calculations\n//#3 Calculation performed the first time\n//#4 Result returned from cache\n//#5 Logging shows calculations performed once each\n"
  },
  {
    "path": "listings/chap09/Listing_09_15_TailRecursive.groovy",
    "content": "import groovy.transform.TailRecursive\n\nclass ListUtil {\n    static reverse(List list) {\n        doReverse(list, [])\n    }\n\n    @TailRecursive\n    private static doReverse(List todo, List done) {\n        if (todo.isEmpty()) done\n        else doReverse(todo.tail(), [todo.head()] + done)\n    }\n}\n\nassert ListUtil.reverse(['a', 'b', 'c']) == ['c', 'b', 'a']\n"
  },
  {
    "path": "listings/chap09/Listing_09_16_Log.groovy",
    "content": "import groovy.util.logging.Log\n\n@Log\nclass Database {\n    def search() {\n        log.fine(runLongDatabaseQuery())\n    }\n\n    def runLongDatabaseQuery() {\n        println 'Calling database'\n        /* ... */\n        return 'query result'\n    }\n}\n\nnew Database().search()\n"
  },
  {
    "path": "listings/chap09/Listing_09_17_Synchronized.groovy",
    "content": "import groovy.transform.Synchronized\n\nclass PhoneBook1 {\n    private final phoneNumbers = [:]\n\n    @Synchronized\n    def getNumber(key) {\n        phoneNumbers[key]\n    }\n\n    @Synchronized\n    void addNumber(key, value) {\n        phoneNumbers[key] = value\n    }\n}\n\ndef p1 = new PhoneBook1()\n(0..99).collect { num ->\n    Thread.start {\n        p1.addNumber('Number' + num, '98765' + num)   //#A\n    }\n}*.join()                                             //#B\nassert p1.getNumber('Number43') == '9876543'          //#C\n//#A Each thread adds a dummy phonebook entry\n//#B Await completion of 99 parallel threads\n//#C Check a sample number\n"
  },
  {
    "path": "listings/chap09/Listing_09_18_SynchronizedCustomLock.groovy",
    "content": "import groovy.transform.Synchronized\nimport groovy.util.logging.Log\n\n@Log\nclass PhoneBook2 {\n    private final phoneNumbers = [:]\n    private final lock = new Object[0]                //#A\n\n    @Synchronized('lock')                             //#B\n    def getNumber(key) {\n            phoneNumbers[key]\n    }\n\n    def addNumber(key, value) {\n        log.info(\"Adding phone number $value\")\n        synchronized (lock) {                         //#C\n            phoneNumbers[key] = value\n        }\n    }\n}\n\ndef p2 = new PhoneBook2()\n(0..99).collect { num ->\n    Thread.start {\n        p2.addNumber('Number' + num, '98765' + num)\n    }\n}*.join()\nassert p2.getNumber('Number43') == '9876543'\n//#A Manually create lock\n//#B Specify the lock name\n//#C Manual synchronized block\n"
  },
  {
    "path": "listings/chap09/Listing_09_19_ReadWriteLock.groovy",
    "content": "import groovy.transform.*\n\nclass PhoneBook3 {\n    private final phoneNumbers = dummyNums()         //#A\n\n    private dummyNums() {\n        (1..8).collectEntries {\n            ['Number' + it, '765432' + it]\n        }\n    }\n\n    @WithReadLock\n    def getNumber(key) {\n        println \"reading started for $key\"\n        phoneNumbers[key]\n        sleep 80\n        println \"reading done for $key\"\n    }\n\n    @WithWriteLock\n    def addNumber(key, value) {\n        println \"writing started for $key\"\n        phoneNumbers[key] = value\n        sleep 100\n        println \"writing done for $key\"\n    }\n}\n\ndef p3 = new PhoneBook3()\n\n(3..4).each{ count ->\n    Thread.start {                                    //#B\n        sleep 100 * count\n        p3.addNumber('Number' + count, '9876543')\n    }\n}\n(2..6).collect{ count ->\n    Thread.start {                                    //#C\n        sleep 100 * count\n        p3.getNumber('Number' + count)\n    }\n}*.join()\n//#A Fill phonebook with dummy numbers\n//#B Start some writer threads\n//#C Start some interleaved reader threads\n/*\nreading started for Number2\nreading started for Number3\nreading done for Number2\nreading done for Number3\nwriting started for Number3\nwriting done for Number3\nreading started for Number4\nreading done for Number4\nwriting started for Number4\nwriting done for Number4\nreading started for Number5\nreading started for Number6\nreading done for Number6\nreading done for Number5\n */"
  },
  {
    "path": "listings/chap09/Listing_09_20_AutoClone.groovy",
    "content": "import groovy.transform.AutoClone\n\n@AutoClone\nclass Chef1 {\n    String name\n    List<String> recipes\n    Date born\n}\n\ndef name = 'Heston Blumenthal'\ndef recipes = ['Snail porridge', 'Bacon & egg ice cream']\ndef born = Date.parse('yyyy-MM-dd', '1966-05-27')\ndef c1 = new Chef1(name: name, recipes: recipes, born: born)\ndef c2 = c1.clone()\nassert c2.recipes == recipes\n"
  },
  {
    "path": "listings/chap09/Listing_09_21_AutoCloneCopyConstructor.groovy",
    "content": "import groovy.transform.*\nimport static groovy.transform.AutoCloneStyle.*\n\n@TupleConstructor\n@AutoClone(style=COPY_CONSTRUCTOR)\nclass Person {\n    final String name\n    final Date born\n}\n\n@TupleConstructor(includeSuperProperties=true,\n        callSuper=true)\n@AutoClone(style=COPY_CONSTRUCTOR)\nclass Chef2 extends Person {\n    final List<String> recipes\n}\n\ndef name = 'Jamie Oliver'\ndef recipes = ['Lentil Soup', 'Crispy Duck']\ndef born = Date.parse('yyyy-MM-dd', '1975-05-27')\ndef c1 = new Chef2(name, born, recipes)\ndef c2 = c1.clone()\nassert c2.name == name\nassert c2.born == born\nassert c2.recipes == recipes\n"
  },
  {
    "path": "listings/chap09/Listing_09_22_AutoExternalize.groovy",
    "content": "import groovy.transform.*\n\n@AutoExternalize\n@ToString\nclass Composer {\n    String name\n    int born\n    boolean married\n}\n\ndef c = new Composer(name: 'Wolfgang Amadeus Mozart',\n        born: 1756, married: true)\n\ndef baos = new ByteArrayOutputStream()\nbaos.withObjectOutputStream{ os -> os.writeObject(c) }\ndef bais = new ByteArrayInputStream(baos.toByteArray())\ndef loader = getClass().classLoader\ndef result\nbais.withObjectInputStream(loader) {\n    result = it.readObject().toString()\n}\nassert result == 'Composer(Wolfgang Amadeus Mozart, 1756, true)'\n"
  },
  {
    "path": "listings/chap09/Listing_09_23_TimedInterrupt.groovy",
    "content": "import groovy.transform.TimedInterrupt\nimport java.util.concurrent.TimeoutException\nimport static java.util.concurrent.TimeUnit.MILLISECONDS\n\n@TimedInterrupt(value = 480L, unit = MILLISECONDS)     //#A\nclass BlastOff1 {\n    def log = []\n\n    def countdown(n) {\n        sleep 100\n        log << n\n        if (n == 0) log << 'ignition'\n        else countdown(n - 1)\n    }\n}\n\ndef b = new BlastOff1()\nThread.start {\n    try {\n        b.countdown(10)\n    } catch (TimeoutException ignore) {\n        b.log << 'aborted'\n    }\n}.join()\nassert b.log.join(' ') == '10 9 8 7 6 aborted'\n//#A Just a little less than 500 milliseconds\n"
  },
  {
    "path": "listings/chap09/Listing_09_24_ThreadInterrupt.groovy",
    "content": "import groovy.transform.ThreadInterrupt\n\n@ThreadInterrupt\nclass BlastOff2 {\n    def log = []\n\n    def countdown(n) {\n        Thread.sleep 100\n        log << n\n        if (n == 0) log << 'ignition'\n        else countdown(n - 1)\n    }\n}\n\ndef b = new BlastOff2()\ndef t1 = Thread.start {\n    try {\n        b.countdown(10)\n    } catch(InterruptedException ignore) {\n        b.log << 'aborted'\n    }\n}\nsleep 590                                          //#A\nt1.interrupt()\nt1.join()\nassert b.log.join(' ') == '10 9 8 7 6 aborted'\n//#A Just a little less than 600 milliseconds\n"
  },
  {
    "path": "listings/chap09/Listing_09_25_ConditionalInterrupt.groovy",
    "content": "import groovy.transform.ConditionalInterrupt\n\n@ConditionalInterrupt({ count <= 5 })\nclass BlastOff3 {\n    def log = []\n    def count = 10\n\n    def countdown() {\n        while (count != 0) {\n            log << count\n            count--\n        }\n        log << 'ignition'\n    }\n}\n\ndef b = new BlastOff3()\ntry {\n    b.countdown()\n} catch (InterruptedException ignore) {\n    b.log << 'aborted'\n}\nassert b.log.join(' ') == '10 9 8 7 6 aborted'\n"
  },
  {
    "path": "listings/chap09/Listing_09_26_Field.groovy",
    "content": "import groovy.transform.Field\n\n@Field List awe = [1, 2, 3]\ndef awesum() { awe.sum() }                       //#A\nassert awesum() == 6\n//#A The variable awe is an instance field of our script\n"
  },
  {
    "path": "listings/chap09/Listing_09_27_BaseScript.groovy",
    "content": "@BaseScript(LoggingScript)\nimport groovy.transform.BaseScript\n\nabstract class LoggingScript extends Script {\n  def log = []\n  void println(args) {\n    log << args\n    System.out.println args\n  }\n}\n\nprintln 'hello'\nprintln 3 * 5\n\nassert log.join(' ') == 'hello 15'\n"
  },
  {
    "path": "listings/chap09/Listing_09_28_AstByHand.groovy",
    "content": "import org.codehaus.groovy.ast.ClassHelper\nimport org.codehaus.groovy.ast.expr.*\nimport org.codehaus.groovy.ast.stmt.ReturnStatement\n\ndef ast = new ReturnStatement(\n    new ConstructorCallExpression(\n        ClassHelper.make(Date),\n        ArgumentListExpression.EMPTY_ARGUMENTS\n    )\n)\n\nassert ast instanceof ReturnStatement\n"
  },
  {
    "path": "listings/chap09/Listing_09_29_AstByHandWithUtils.groovy",
    "content": "import org.codehaus.groovy.ast.stmt.ReturnStatement\nimport static org.codehaus.groovy.ast.ClassHelper.make\nimport static org.codehaus.groovy.ast.tools.GeneralUtils.*\n\ndef ast = returnS(ctorX(make(Date)))\nassert ast instanceof ReturnStatement\n"
  },
  {
    "path": "listings/chap09/Listing_09_30_AstBuildFromSpec.groovy",
    "content": "import org.codehaus.groovy.ast.builder.AstBuilder\nimport org.codehaus.groovy.ast.stmt.ReturnStatement\n\ndef ast = new AstBuilder().buildFromSpec {\n  returnStatement {\n    constructorCall(Date) {\n      argumentList {}\n    }\n  }\n}\n\nassert ast[0] instanceof ReturnStatement\n"
  },
  {
    "path": "listings/chap09/Listing_09_31_AstBuildFromString.groovy",
    "content": "import org.codehaus.groovy.ast.builder.AstBuilder\nimport org.codehaus.groovy.ast.stmt.BlockStatement\nimport org.codehaus.groovy.ast.stmt.ReturnStatement\n\ndef ast = new AstBuilder().buildFromString('new Date()')\nassert ast[0] instanceof BlockStatement\nassert ast[0].statements[0] instanceof ReturnStatement\n"
  },
  {
    "path": "listings/chap09/Listing_09_32_AstBuildFromStringMixed.groovy",
    "content": "import org.codehaus.groovy.ast.builder.AstBuilder\nimport org.codehaus.groovy.control.CompilePhase\nimport org.codehaus.groovy.ast.*\n\ndef approxPI = 3.14G\ndef ast = new AstBuilder().buildFromString(\n    CompilePhase.CLASS_GENERATION,\n    false,\n    'static double getTwoPI() { def pi = ' + approxPI + '; pi * 2 }'\n)\n\nassert ast[1] instanceof ClassNode\ndef method = ast[1].methods.find { it.name == 'getTwoPI' }\nassert method instanceof MethodNode\n"
  },
  {
    "path": "listings/chap09/Listing_09_33_AstBuildFromCode.groovy",
    "content": "import org.codehaus.groovy.ast.builder.AstBuilder\nimport org.codehaus.groovy.ast.stmt.ReturnStatement\n\ndef ast = new AstBuilder().buildFromCode {\n  new Date()\n}\nassert ast[0].statements[0] instanceof ReturnStatement\n"
  },
  {
    "path": "listings/chap09/Listing_09_34_GreeterMainTransform.groovy",
    "content": "import org.codehaus.groovy.ast.*\nimport org.codehaus.groovy.transform.*\nimport java.lang.annotation.*\nimport org.codehaus.groovy.control.*\n\n@Retention(RetentionPolicy.SOURCE)                              //#A\n@Target([ElementType.METHOD])                                   //#A\n@GroovyASTTransformationClass(classes = [MainTransformation])   //#A\n@interface Main {}                                              //#A\n\nimport static groovyjarjarasm.asm.Opcodes.*\nimport static org.codehaus.groovy.ast.ClassHelper.VOID_TYPE\nimport static org.codehaus.groovy.ast.tools.GeneralUtils.*\n\n@GroovyASTTransformation(phase = CompilePhase.INSTRUCTION_SELECTION)\nclass MainTransformation implements ASTTransformation {\n  private NO_EXCEPTIONS = ClassNode.EMPTY_ARRAY\n  private STRING_ARRAY = ClassHelper.STRING_TYPE.makeArray()\n\n  void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {\n    if (astNodes?.size() != 2) return                           //#B\n    if (!(astNodes[0] instanceof AnnotationNode)) return        //#B\n    if (astNodes[0].classNode.name != Main.name) return         //#B\n    if (!(astNodes[1] instanceof MethodNode)) return            //#B\n\n    def targetMethod = astNodes[1]\n    def targetClass = targetMethod.declaringClass\n    def targetInstance = ctorX(targetClass)\n    def callTarget = callX(targetInstance, targetMethod.name)   //#C\n    def mainBody = block(stmt(callTarget))\n    def visibility = ACC_STATIC | ACC_PUBLIC\n    def parameters = params(param(STRING_ARRAY, 'args'))\n    targetClass.addMethod('main', visibility,                   //#D\n        VOID_TYPE, parameters, NO_EXCEPTIONS, mainBody)         //#D\n  }\n}\n\nnew GroovyShell(getClass().classLoader).evaluate '''\nclass Greeter {\n  @Main\n  def greet() {\n    println \"Hello from the greet() method!\"\n  }\n}\n'''\n//#A Annotation class definition\n//#B Defensive programming via guard clauses\n//#C new Greeter().greet()\n//#D add public static void main method\n"
  },
  {
    "path": "listings/chap09/Listing_09_35_GreeterMainTransform2.groovy",
    "content": "import org.codehaus.groovy.ast.*\nimport org.codehaus.groovy.ast.stmt.BlockStatement\nimport org.codehaus.groovy.transform.*\nimport java.lang.annotation.*\nimport org.codehaus.groovy.control.*\n\n@Retention(RetentionPolicy.SOURCE)\n@Target([ElementType.METHOD])\n@GroovyASTTransformationClass(classes = [MainTransformation2])\n@interface Main2 {\n  boolean merge() default false                                       //#A\n}\n\nimport static org.codehaus.groovy.ast.ClassHelper.VOID_TYPE\nimport static org.codehaus.groovy.ast.tools.GeneralUtils.*\n\n@GroovyASTTransformation(phase = CompilePhase.INSTRUCTION_SELECTION)\nclass MainTransformation2 extends AbstractASTTransformation {\n  private MSG1 = \"@Main2 annotation use requires no-arg constructor!\"\n  private MSG2 = \"@Main2 annotation used but main already exists!\"\n  private NO_EXCEPTIONS = ClassNode.EMPTY_ARRAY\n  private NO_PARAMS = Parameter.EMPTY_ARRAY\n  private STRING_ARRAY = ClassHelper.STRING_TYPE.makeArray()\n\n  void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {\n    init(astNodes, sourceUnit)\n    def (anno, mainMethod) = astNodes\n\n    boolean merge = getMemberValue(anno, 'merge')                     //#B\n    def mainClass = mainMethod.declaringClass\n    def callTarget\n    if (mainMethod.isStatic()) {\n      callTarget = mainClass\n    } else {\n      if (!hasNoArgConstructor(mainClass)) {\n        addError(MSG1, mainMethod)                                    //#C\n        return\n      }\n      callTarget = ctorX(mainClass)\n    }\n    def callStatement = stmt(callX(callTarget, mainMethod.name))\n    def parameters = params(param(STRING_ARRAY, 'args'))\n    def existingMain = mainClass.getDeclaredMethod('main', parameters)\n    if (existingMain && !merge) {\n      addError(MSG2, mainMethod)                                      //#D\n      return\n    }\n\n    if (existingMain) {\n      if (existingMain.code instanceof BlockStatement) {\n        existingMain.code.addStatement(callStatement)                 //#E\n      } else {\n        block(existingMain.code).addStatement(callStatement)          //#F\n      }\n    } else {\n      mainClass.addMethod('main', ACC_STATIC | ACC_PUBLIC,\n          VOID_TYPE, parameters, NO_EXCEPTIONS, block(callStatement))\n    }\n  }\n\n  private hasNoArgConstructor(mainClass) {\n    def constructors = mainClass.declaredConstructors\n    def explicitNoArg = constructors.find { it.parameters == NO_PARAMS }\n    def implicitNoArg = constructors.size() == 0\n    implicitNoArg || explicitNoArg\n  }\n}\n\nnew GroovyShell(getClass().classLoader).evaluate '''\nclass Greeter {\n    public static void main(String[] args) {\n        println 'Hello from main()'\n    }\n\n    @Main2(merge=true)\n    def greet() {\n        println \"Hello from the greet() instance method!\"\n    }\n\n    @Main2(merge=true)\n    static greet2() {\n        println \"Hello from the greet2() static method!\"\n    }\n}\n'''\n//#A Define an annotation attribute\n//#B Read annotation attribute value\n//#C Indicate error if missing no-arg constructor\n//#D Indicate error unless explicit merging\n//#E Handle block statement case\n//#F Handle single statement case\n"
  },
  {
    "path": "listings/chap09/Listing_09_38_AstTesting1.groovy",
    "content": "import groovy.transform.WithReadLock\nimport java.util.concurrent.locks.ReentrantReadWriteLock\nimport static java.lang.reflect.Modifier.*\n\nclass ReadWriteLockTestWithNestedClass extends GroovyTestCase {\n\n  static class MyClass {                            //#A\n    @WithReadLock\n    void readerMethod1() {}\n  }\n\n  void testLockFieldDefaultsForReadLock() {\n    def field = MyClass.getDeclaredField('$reentrantlock')\n    assert isPrivate(field.modifiers)\n    assert !isTransient(field.modifiers)\n    assert isFinal(field.modifiers)\n    assert !isStatic(field.modifiers)\n    assert field.type == ReentrantReadWriteLock\n  }\n}\n//#A Nested class\n"
  },
  {
    "path": "listings/chap09/Listing_09_39_AstTesting2.groovy",
    "content": "import java.util.concurrent.locks.ReentrantReadWriteLock\nimport static java.lang.reflect.Modifier.*\n\nclass ReadWriteLockTestClassLoader extends GroovyTestCase {\n\n  public void testLockFieldDefaultsForReadLock() {\n    def tester = new GroovyClassLoader().parseClass('''\n      class MyClass {\n        @groovy.transform.WithReadLock\n        public void readerMethod1() { }\n      }\n    ''')\n\n    def field = tester.getDeclaredField('$reentrantlock')\n    assert isPrivate(field.modifiers)\n    assert !isTransient(field.modifiers)\n    assert isFinal(field.modifiers)\n    assert !isStatic(field.modifiers)\n    assert field.type == ReentrantReadWriteLock\n  }\n}\n"
  },
  {
    "path": "listings/chap09/Listing_09_40_AstTesting3.groovy",
    "content": "import java.lang.reflect.Modifier\n\nclass ReadWriteLockTestGroovyShell extends GroovyTestCase {\n\n  public void testLockFieldDefaultsForReadLock() {\n    def tester = new GroovyShell().evaluate('''\n      import groovy.transform.WithReadLock\n      class MyClass {\n        @WithReadLock\n        public void readerMethod1() { }\n      }\n      new MyClass()\n    ''')\n\n    def field = tester.getClass().getDeclaredField('$reentrantlock')\n    assert Modifier.isPrivate(field.modifiers)\n    // and more assertions...\n  }\n}\n"
  },
  {
    "path": "listings/chap09/Listing_09_41_AstTesting4.groovy",
    "content": "import org.codehaus.groovy.tools.ast.TransformTestHelper\nimport static groovy.test.GroovyAssert.shouldFail\nimport static org.codehaus.groovy.control.CompilePhase.*\n\ndef DATE_FMT = /\\w{3} \\w{3} \\d\\d \\d\\d:\\d\\d:\\d\\d \\S{3,9} \\d{4}/\n\ndef folder = new File('src/main/groovy/regina')\ndef source = new File(folder, 'CompiledAtASTTransformation.groovy')\ndef transform = getClass().classLoader.parseClass(source).newInstance()\n\ndef helper = new TransformTestHelper(transform, PARSING)\ndef clazz = helper.parse(' class MyClass {} ')\nshouldFail(MissingMethodException) {\n  clazz.getCompileTime()\n}\n\nhelper = new TransformTestHelper(transform, CONVERSION)\nclazz = helper.parse(' class MyClass {} ')\nassert clazz.getCompiledTime()\nassert clazz.getCompiledTime() =~ DATE_FMT\n"
  },
  {
    "path": "listings/chap09/Listing_09_42_AstTesting5.groovy",
    "content": "import groovy.transform.ASTTest\nimport org.codehaus.groovy.ast.stmt.ForStatement\nimport org.codehaus.groovy.control.CompilePhase\n\n@ASTTest(phase=CompilePhase.SEMANTIC_ANALYSIS, value={       //#A\n  lookup('anchor').each { n ->                               //#B\n    assert n instanceof ForStatement                         //#C\n  }\n})\nvoid doSomething() {\n  println 'Hello, Groovy!'\n  anchor: for (int i=0; i<10;i++) { println \"Iteration $i\" } //#D\n}\n//#A annotate an enclosing node\n//#B call lookup to find a node labeled with “anchor”\n//#C perform assertion on each matching node\n//#D use a label on the node\n"
  },
  {
    "path": "listings/chap09/Listings.txt",
    "content": "Listings not in the root folder:\n09_36: src/main/groovy/regina/CompiledAtASTTransformation.groovy\n09_37: src/test/groovy/regina/CompiledAtASTTransformationTest.groovy\n"
  },
  {
    "path": "listings/chap09/build/reports/tests/classes/regina.CompiledAtASTTransformationTest.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n<meta http-equiv=\"x-ua-compatible\" content=\"IE=edge\"/>\n<title>Test results - Class regina.CompiledAtASTTransformationTest</title>\n<link href=\"../css/base-style.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"../css/style.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<script src=\"../js/report.js\" type=\"text/javascript\"></script>\n</head>\n<body>\n<div id=\"content\">\n<h1>Class regina.CompiledAtASTTransformationTest</h1>\n<div class=\"breadcrumbs\">\n<a href=\"../index.html\">all</a> &gt; \n<a href=\"../packages/regina.html\">regina</a> &gt; CompiledAtASTTransformationTest</div>\n<div id=\"summary\">\n<table>\n<tr>\n<td>\n<div class=\"summaryGroup\">\n<table>\n<tr>\n<td>\n<div class=\"infoBox\" id=\"tests\">\n<div class=\"counter\">2</div>\n<p>tests</p>\n</div>\n</td>\n<td>\n<div class=\"infoBox\" id=\"failures\">\n<div class=\"counter\">0</div>\n<p>failures</p>\n</div>\n</td>\n<td>\n<div class=\"infoBox\" id=\"ignored\">\n<div class=\"counter\">0</div>\n<p>ignored</p>\n</div>\n</td>\n<td>\n<div class=\"infoBox\" id=\"duration\">\n<div class=\"counter\">0.446s</div>\n<p>duration</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</td>\n<td>\n<div class=\"infoBox success\" id=\"successRate\">\n<div class=\"percent\">100%</div>\n<p>successful</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n<div id=\"tabs\">\n<ul class=\"tabLinks\">\n<li>\n<a href=\"#tab0\">Tests</a>\n</li>\n</ul>\n<div id=\"tab0\" class=\"tab\">\n<h2>Tests</h2>\n<table>\n<thead>\n<tr>\n<th>Test</th>\n<th>Duration</th>\n<th>Result</th>\n</tr>\n</thead>\n<tr>\n<td class=\"success\">testShouldApplyToScriptAndScriptClasses</td>\n<td>0.446s</td>\n<td class=\"success\">passed</td>\n</tr>\n<tr>\n<td class=\"success\">testShouldApplyToThisTest</td>\n<td>0s</td>\n<td class=\"success\">passed</td>\n</tr>\n</table>\n</div>\n</div>\n<div id=\"footer\">\n<p>Generated by \n<a href=\"http://www.gradle.org\">Gradle 2.2.1</a> at 01.02.2015 17:04:38</p>\n</div>\n</div>\n</body>"
  },
  {
    "path": "listings/chap09/build/reports/tests/css/base-style.css",
    "content": "\nbody {\n    margin: 0;\n    padding: 0;\n    font-family: sans-serif;\n    font-size: 12pt;\n}\n\nbody, a, a:visited {\n    color: #303030;\n}\n\n#content {\n    padding-left: 50px;\n    padding-right: 50px;\n    padding-top: 30px;\n    padding-bottom: 30px;\n}\n\n#content h1 {\n    font-size: 160%;\n    margin-bottom: 10px;\n}\n\n#footer {\n    margin-top: 100px;\n    font-size: 80%;\n    white-space: nowrap;\n}\n\n#footer, #footer a {\n    color: #a0a0a0;\n}\n\nul {\n    margin-left: 0;\n}\n\nh1, h2, h3 {\n    white-space: nowrap;\n}\n\nh2 {\n    font-size: 120%;\n}\n\nul.tabLinks {\n    padding-left: 0;\n    padding-top: 10px;\n    padding-bottom: 10px;\n    overflow: auto;\n    min-width: 800px;\n    width: auto !important;\n    width: 800px;\n}\n\nul.tabLinks li {\n    float: left;\n    height: 100%;\n    list-style: none;\n    padding-left: 10px;\n    padding-right: 10px;\n    padding-top: 5px;\n    padding-bottom: 5px;\n    margin-bottom: 0;\n    -moz-border-radius: 7px;\n    border-radius: 7px;\n    margin-right: 25px;\n    border: solid 1px #d4d4d4;\n    background-color: #f0f0f0;\n}\n\nul.tabLinks li:hover {\n    background-color: #fafafa;\n}\n\nul.tabLinks li.selected {\n    background-color: #c5f0f5;\n    border-color: #c5f0f5;\n}\n\nul.tabLinks a {\n    font-size: 120%;\n    display: block;\n    outline: none;\n    text-decoration: none;\n    margin: 0;\n    padding: 0;\n}\n\nul.tabLinks li h2 {\n    margin: 0;\n    padding: 0;\n}\n\ndiv.tab {\n}\n\ndiv.selected {\n    display: block;\n}\n\ndiv.deselected {\n    display: none;\n}\n\ndiv.tab table {\n    min-width: 350px;\n    width: auto !important;\n    width: 350px;\n    border-collapse: collapse;\n}\n\ndiv.tab th, div.tab table {\n    border-bottom: solid #d0d0d0 1px;\n}\n\ndiv.tab th {\n    text-align: left;\n    white-space: nowrap;\n    padding-left: 6em;\n}\n\ndiv.tab th:first-child {\n    padding-left: 0;\n}\n\ndiv.tab td {\n    white-space: nowrap;\n    padding-left: 6em;\n    padding-top: 5px;\n    padding-bottom: 5px;\n}\n\ndiv.tab td:first-child {\n    padding-left: 0;\n}\n\ndiv.tab td.numeric, div.tab th.numeric {\n    text-align: right;\n}\n\nspan.code {\n    display: inline-block;\n    margin-top: 0em;\n    margin-bottom: 1em;\n}\n\nspan.code pre {\n    font-size: 11pt;\n    padding-top: 10px;\n    padding-bottom: 10px;\n    padding-left: 10px;\n    padding-right: 10px;\n    margin: 0;\n    background-color: #f7f7f7;\n    border: solid 1px #d0d0d0;\n    min-width: 700px;\n    width: auto !important;\n    width: 700px;\n}\n"
  },
  {
    "path": "listings/chap09/build/reports/tests/css/style.css",
    "content": "\n#summary {\n    margin-top: 30px;\n    margin-bottom: 40px;\n}\n\n#summary table {\n    border-collapse: collapse;\n}\n\n#summary td {\n    vertical-align: top;\n}\n\n.breadcrumbs, .breadcrumbs a {\n    color: #606060;\n}\n\n.infoBox {\n    width: 110px;\n    padding-top: 15px;\n    padding-bottom: 15px;\n    text-align: center;\n}\n\n.infoBox p {\n    margin: 0;\n}\n\n.counter, .percent {\n    font-size: 120%;\n    font-weight: bold;\n    margin-bottom: 8px;\n}\n\n#duration {\n    width: 125px;\n}\n\n#successRate, .summaryGroup {\n    border: solid 2px #d0d0d0;\n    -moz-border-radius: 10px;\n    border-radius: 10px;\n}\n\n#successRate {\n    width: 140px;\n    margin-left: 35px;\n}\n\n#successRate .percent {\n    font-size: 180%;\n}\n\n.success, .success a {\n    color: #008000;\n}\n\ndiv.success, #successRate.success {\n    background-color: #bbd9bb;\n    border-color: #008000;\n}\n\n.failures, .failures a {\n    color: #b60808;\n}\n\n.skipped, .skipped a {\n    color: #c09853;\n}\n\ndiv.failures, #successRate.failures {\n    background-color: #ecdada;\n    border-color: #b60808;\n}\n\nul.linkList {\n    padding-left: 0;\n}\n\nul.linkList li {\n    list-style: none;\n    margin-bottom: 5px;\n}\n"
  },
  {
    "path": "listings/chap09/build/reports/tests/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n<meta http-equiv=\"x-ua-compatible\" content=\"IE=edge\"/>\n<title>Test results - Test Summary</title>\n<link href=\"css/base-style.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"css/style.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<script src=\"js/report.js\" type=\"text/javascript\"></script>\n</head>\n<body>\n<div id=\"content\">\n<h1>Test Summary</h1>\n<div id=\"summary\">\n<table>\n<tr>\n<td>\n<div class=\"summaryGroup\">\n<table>\n<tr>\n<td>\n<div class=\"infoBox\" id=\"tests\">\n<div class=\"counter\">2</div>\n<p>tests</p>\n</div>\n</td>\n<td>\n<div class=\"infoBox\" id=\"failures\">\n<div class=\"counter\">0</div>\n<p>failures</p>\n</div>\n</td>\n<td>\n<div class=\"infoBox\" id=\"ignored\">\n<div class=\"counter\">0</div>\n<p>ignored</p>\n</div>\n</td>\n<td>\n<div class=\"infoBox\" id=\"duration\">\n<div class=\"counter\">0.446s</div>\n<p>duration</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</td>\n<td>\n<div class=\"infoBox success\" id=\"successRate\">\n<div class=\"percent\">100%</div>\n<p>successful</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n<div id=\"tabs\">\n<ul class=\"tabLinks\">\n<li>\n<a href=\"#tab0\">Packages</a>\n</li>\n<li>\n<a href=\"#tab1\">Classes</a>\n</li>\n</ul>\n<div id=\"tab0\" class=\"tab\">\n<h2>Packages</h2>\n<table>\n<thead>\n<tr>\n<th>Package</th>\n<th>Tests</th>\n<th>Failures</th>\n<th>Ignored</th>\n<th>Duration</th>\n<th>Success rate</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"success\">\n<a href=\"packages/regina.html\">regina</a>\n</td>\n<td>2</td>\n<td>0</td>\n<td>0</td>\n<td>0.446s</td>\n<td class=\"success\">100%</td>\n</tr>\n</tbody>\n</table>\n</div>\n<div id=\"tab1\" class=\"tab\">\n<h2>Classes</h2>\n<table>\n<thead>\n<tr>\n<th>Class</th>\n<th>Tests</th>\n<th>Failures</th>\n<th>Ignored</th>\n<th>Duration</th>\n<th>Success rate</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"success\"/>\n<a href=\"classes/regina.CompiledAtASTTransformationTest.html\">regina.CompiledAtASTTransformationTest</a>\n<td>2</td>\n<td>0</td>\n<td>0</td>\n<td>0.446s</td>\n<td class=\"success\">100%</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n<div id=\"footer\">\n<p>Generated by \n<a href=\"http://www.gradle.org\">Gradle 2.2.1</a> at 01.02.2015 17:04:38</p>\n</div>\n</div>\n</body>"
  },
  {
    "path": "listings/chap09/build/reports/tests/js/report.js",
    "content": "var tabs = new Object();\n\nfunction initTabs() {\n    var container = document.getElementById('tabs');\n    tabs.tabs = findTabs(container);\n    tabs.titles = findTitles(tabs.tabs);\n    tabs.headers = findHeaders(container);\n    tabs.select = select;\n    tabs.deselectAll = deselectAll;\n    tabs.select(0);\n    return true;\n}\n\nwindow.onload = initTabs;\n\nfunction switchTab() {\n    var id = this.id.substr(1);\n    for (var i = 0; i < tabs.tabs.length; i++) {\n        if (tabs.tabs[i].id == id) {\n            tabs.select(i);\n            break;\n        }\n    }\n    return false;\n}\n\nfunction select(i) {\n    this.deselectAll();\n    changeElementClass(this.tabs[i], 'tab selected');\n    changeElementClass(this.headers[i], 'selected');\n    while (this.headers[i].firstChild) {\n        this.headers[i].removeChild(this.headers[i].firstChild);\n    }\n    var h2 = document.createElement('H2');\n    h2.appendChild(document.createTextNode(this.titles[i]));\n    this.headers[i].appendChild(h2);\n}\n\nfunction deselectAll() {\n    for (var i = 0; i < this.tabs.length; i++) {\n        changeElementClass(this.tabs[i], 'tab deselected');\n        changeElementClass(this.headers[i], 'deselected');\n        while (this.headers[i].firstChild) {\n            this.headers[i].removeChild(this.headers[i].firstChild);\n        }\n        var a = document.createElement('A');\n        a.setAttribute('id', 'ltab' + i);\n        a.setAttribute('href', '#tab' + i);\n        a.onclick = switchTab;\n        a.appendChild(document.createTextNode(this.titles[i]));\n        this.headers[i].appendChild(a);\n    }\n}\n\nfunction changeElementClass(element, classValue) {\n    if (element.getAttribute('className')) {\n        /* IE */\n        element.setAttribute('className', classValue)\n    } else {\n        element.setAttribute('class', classValue)\n    }\n}\n\nfunction findTabs(container) {\n    return findChildElements(container, 'DIV', 'tab');\n}\n\nfunction findHeaders(container) {\n    var owner = findChildElements(container, 'UL', 'tabLinks');\n    return findChildElements(owner[0], 'LI', null);\n}\n\nfunction findTitles(tabs) {\n    var titles = new Array();\n    for (var i = 0; i < tabs.length; i++) {\n        var tab = tabs[i];\n        var header = findChildElements(tab, 'H2', null)[0];\n        header.parentNode.removeChild(header);\n        if (header.innerText) {\n            titles.push(header.innerText)\n        } else {\n            titles.push(header.textContent)\n        }\n    }\n    return titles;\n}\n\nfunction findChildElements(container, name, targetClass) {\n    var elements = new Array();\n    var children = container.childNodes;\n    for (var i = 0; i < children.length; i++) {\n        var child = children.item(i);\n        if (child.nodeType == 1 && child.nodeName == name) {\n            if (targetClass && child.className.indexOf(targetClass) < 0) {\n                continue;\n            }\n            elements.push(child);\n        }\n    }\n    return elements;\n}\n"
  },
  {
    "path": "listings/chap09/build/reports/tests/packages/regina.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n<meta http-equiv=\"x-ua-compatible\" content=\"IE=edge\"/>\n<title>Test results - Package regina</title>\n<link href=\"../css/base-style.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<link href=\"../css/style.css\" rel=\"stylesheet\" type=\"text/css\"/>\n<script src=\"../js/report.js\" type=\"text/javascript\"></script>\n</head>\n<body>\n<div id=\"content\">\n<h1>Package regina</h1>\n<div class=\"breadcrumbs\">\n<a href=\"../index.html\">all</a> &gt; regina</div>\n<div id=\"summary\">\n<table>\n<tr>\n<td>\n<div class=\"summaryGroup\">\n<table>\n<tr>\n<td>\n<div class=\"infoBox\" id=\"tests\">\n<div class=\"counter\">2</div>\n<p>tests</p>\n</div>\n</td>\n<td>\n<div class=\"infoBox\" id=\"failures\">\n<div class=\"counter\">0</div>\n<p>failures</p>\n</div>\n</td>\n<td>\n<div class=\"infoBox\" id=\"ignored\">\n<div class=\"counter\">0</div>\n<p>ignored</p>\n</div>\n</td>\n<td>\n<div class=\"infoBox\" id=\"duration\">\n<div class=\"counter\">0.446s</div>\n<p>duration</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</td>\n<td>\n<div class=\"infoBox success\" id=\"successRate\">\n<div class=\"percent\">100%</div>\n<p>successful</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n<div id=\"tabs\">\n<ul class=\"tabLinks\">\n<li>\n<a href=\"#tab0\">Classes</a>\n</li>\n</ul>\n<div id=\"tab0\" class=\"tab\">\n<h2>Classes</h2>\n<table>\n<thread>\n<tr>\n<th>Class</th>\n<th>Tests</th>\n<th>Failures</th>\n<th>Ignored</th>\n<th>Duration</th>\n<th>Success rate</th>\n</tr>\n</thread>\n<tr>\n<td class=\"success\">\n<a href=\"../classes/regina.CompiledAtASTTransformationTest.html\">CompiledAtASTTransformationTest</a>\n</td>\n<td>2</td>\n<td>0</td>\n<td>0</td>\n<td>0.446s</td>\n<td class=\"success\">100%</td>\n</tr>\n</table>\n</div>\n</div>\n<div id=\"footer\">\n<p>Generated by \n<a href=\"http://www.gradle.org\">Gradle 2.2.1</a> at 01.02.2015 17:04:38</p>\n</div>\n</div>\n</body>"
  },
  {
    "path": "listings/chap09/build/resources/main/META-INF/services/org.codehaus.groovy.transform.ASTTransformation",
    "content": "regina.CompiledAtASTTransformation"
  },
  {
    "path": "listings/chap09/build/test-results/TEST-regina.CompiledAtASTTransformationTest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<testsuite name=\"regina.CompiledAtASTTransformationTest\" tests=\"2\" skipped=\"0\" failures=\"0\" errors=\"0\" timestamp=\"2015-02-01T16:04:37\" hostname=\"Dierk-Konigs-MacBook-Pro.local\" time=\"0.446\">\n  <properties/>\n  <testcase name=\"testShouldApplyToScriptAndScriptClasses\" classname=\"regina.CompiledAtASTTransformationTest\" time=\"0.446\"/>\n  <testcase name=\"testShouldApplyToThisTest\" classname=\"regina.CompiledAtASTTransformationTest\" time=\"0.0\"/>\n  <system-out><![CDATA[]]></system-out>\n  <system-err><![CDATA[]]></system-err>\n</testsuite>\n"
  },
  {
    "path": "listings/chap09/build.gradle",
    "content": "apply plugin:'idea'\napply plugin:'groovy'\napply plugin:'java'\n\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    compile     \"org.codehaus.groovy:groovy-all:$groovyVersion\"\n    testCompile \"org.codehaus.groovy:groovy-all:$groovyVersion\"\n    testCompile \"junit:junit:4.12\"\n}\n\n[compileGroovy, compileTestGroovy]*.options*.encoding = 'UTF-8'\n\n"
  },
  {
    "path": "listings/chap09/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Thu Apr 10 09:16:15 EST 2014\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=http\\://services.gradle.org/distributions/gradle-2.2.1-bin.zip\n"
  },
  {
    "path": "listings/chap09/gradle.properties",
    "content": "version=1.0.0-SNAPSHOT\ngroovyVersion=2.4.0\n"
  },
  {
    "path": "listings/chap09/gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# For Cygwin, ensure paths are in UNIX format before anything is touched.\nif $cygwin ; then\n    [ -n \"$JAVA_HOME\" ] && JAVA_HOME=`cygpath --unix \"$JAVA_HOME\"`\nfi\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >&-\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >&-\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "listings/chap09/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "listings/chap09/settings.gradle",
    "content": "rootProject.name='regina-chap09'\n\n\n"
  },
  {
    "path": "listings/chap09/snippet0902_autoCloneDefault.txt",
    "content": "class Chef1 implements Cloneable {\n    ...\n    Chef1 clone() throws CloneNotSupportedException {\n        Chef1 _result = (Chef1) super.clone()\n        if (recipes instanceof Cloneable) {\n            _result.recipes = (List<String>) recipes.clone()\n        }\n        _result.born = (Date) born.clone()\n        return _result\n    }\n}\n"
  },
  {
    "path": "listings/chap09/snippet0902_autoCloneSerialization.txt",
    "content": "class Chef1 implements Cloneable, Serializable {\n  ...\n  Object clone() throws CloneNotSupportedException {\n    def baos = new ByteArrayOutputStream()\n    baos.withObjectOutputStream{ it.writeObject(this) }\n    def bais = new ByteArrayInputStream(baos.toByteArray())\n    bais.withObjectInputStream(getClass().classLoader){ it.readObject() }\n  }\n}\n"
  },
  {
    "path": "listings/chap09/snippet0902_autoExternalize.txt",
    "content": "class Composer implements Externalizable {\n    ...\n    void writeExternal(ObjectOutput out) throws IOException {\n        out.writeObject(name)\n        out.writeInt(born)\n        out.writeBoolean(married)\n    }\n\n    void readExternal(ObjectInput oin) {\n        name = (String) oin.readObject()\n        born = oin.readInt()\n        married = oin.readBoolean()\n    }\n}\n"
  },
  {
    "path": "listings/chap09/snippet0902_fieldEquivalent.txt",
    "content": "class ScriptYYYYY extends Script {\n  List awe = [1, 2, 3]\n\n  public static void main(String[] args) {\n    new ScriptYYYYY().run()                      //#A\n  }\n\n  public awesum() {\n    awe.sum()\n  }\n\n  public run() {\n    assert awesum() == 6\n  }\n}\n//#A again slightly simplified\n"
  },
  {
    "path": "listings/chap09/snippet0902_mapCreation.txt",
    "content": "class Chemist {\n    String first, last\n    int born\n}\n\ndef c = new Chemist(first: \"Marie\", last: \"Curie\", born: 1867)\nassert c.first == \"Marie\"\nassert c.last == \"Curie\"\nassert c.born == 1867\n"
  },
  {
    "path": "listings/chap09/snippet0902_noisySetDelegateByHand.txt",
    "content": "class NoisySet implements Set {\n    private Set delegate = new HashSet()\n\n    @Override\n    boolean add(item) {\n        println \"adding $item\"\n        delegate.add(item)\n    }\n\n    @Override\n    boolean addAll(Collection items) {\n        items.each { println \"adding $it\" }\n        delegate.addAll(items)\n    }\n\n    @Override\n    boolean isEmpty() {\n        return delegate.isEmpty()\n    }\n\n    @Override\n    boolean contains(Object o) {\n        return delegate.contains(o)\n    }\n\n    // ... ditto for size, iterator, toArray, remove,\n    // containsAll, retainAll, removeAll, clear ...\n\n    @Override\n    int size() {\n        return delegate.size()\n    }\n\n    @Override\n    Iterator iterator() {\n        return delegate.iterator()\n    }\n\n    @Override\n    Object[] toArray() {\n        return delegate.toArray()\n    }\n\n    @Override\n    def Object[] toArray(Object[] a) {\n        return delegate.toArray(a)\n    }\n\n    @Override\n    boolean remove(Object o) {\n        return delegate.remove(o)\n    }\n\n    @Override\n    boolean containsAll(Collection<?> c) {\n        return delegate.containsAll(c)\n    }\n\n    @Override\n    boolean retainAll(Collection<?> c) {\n        return delegate.retainAll(c)\n    }\n\n    @Override\n    boolean removeAll(Collection<?> c) {\n        return delegate.removeAll(c)\n    }\n\n    @Override\n    void clear() {\n        delegate.clear()\n    }\n}\n\nSet ns = new NoisySet()\nns.add(1)\nns.addAll([2, 3])\nassert ns.size() == 3\n"
  },
  {
    "path": "listings/chap09/snippet0902_noisySetInheritance.txt",
    "content": "class NoisySet extends HashSet {\n    @Override\n    boolean add(item) {\n        println \"adding $item\"\n        super.add(item)\n    }\n\n    @Override\n    boolean addAll(Collection items) {\n        items.each { println \"adding $it\" }\n        super.addAll(items)\n    }\n}\n\nnew NoisySet().with{\n    add(1)\n    addAll([2, 3])\n    assert size() == 3\n}\n"
  },
  {
    "path": "listings/chap09/snippet0902_nonTailCallReverseList.txt",
    "content": "class ListUtil {\n    static reverse(List list) {\n        if (list.isEmpty()) list\n        else reverse(list.tail()) + list.head()\n    }\n}\n\nassert ListUtil.reverse(['a', 'b', 'c']) == ['c', 'b', 'a']\n"
  },
  {
    "path": "listings/chap09/snippet0902_readWriteByHand.txt",
    "content": "import java.util.concurrent.locks.ReentrantReadWriteLock\n\nclass PhoneBook3 {\n    private final phoneNumbers = [:]\n    final private lock = new ReentrantReadWriteLock()\n\n    def getNumber(key) {\n        lock.readLock().lock()\n        try {\n            phoneNumbers[key]\n        } finally {\n            lock.readLock().unlock()\n        }\n    }\n\n    def addNumber(key, value) {\n        lock.writeLock().lock()\n        try {\n            phoneNumbers[key] = value\n        } finally {\n            lock.writeLock().unlock()\n        }\n    }\n}\n"
  },
  {
    "path": "listings/chap09/snippet0902_readWriteLock.txt",
    "content": "import groovy.transform.*\n\nclass PhoneBook3 {\n    private final phoneNumbers = [:]\n\n    @WithReadLock\n    def getNumber(key) {\n        phoneNumbers[key]\n    }\n\n    @WithWriteLock\n    def addNumber(key, value) {\n        phoneNumbers[key] = value\n    }\n}\n"
  },
  {
    "path": "listings/chap09/snippet0902_singletonByHand.txt",
    "content": "class Zeus {\n    static final Zeus instance = new Zeus()\n    private Zeus() { }\n}\n\nassert Zeus.instance\n"
  },
  {
    "path": "listings/chap09/snippet0902_toStringEquivalent.txt",
    "content": "import org.codehaus.groovy.runtime.InvokerHelper\n\nclass SleuthExpanded {\n\n  String firstName\n  String lastName\n\n  String toString() {\n    def _result = new StringBuilder()\n    def $toStringFirst = true\n    _result.append('Sleuth(')\n\n    def firstName = InvokerHelper.getProperty(this, 'firstName')\n    if (firstName != null) {\n      if ($toStringFirst) {\n        $toStringFirst = false\n      } else {\n        _result.append(', ')\n      }\n      _result.append('firstName:')\n      if (firstName.is(this)) {\n        _result.append('(this)')\n      } else {\n        _result.append(InvokerHelper.toString(firstName))\n      }\n    }\n\n    def lastName = InvokerHelper.getProperty(this, 'lastName')\n    if (lastName != null) {\n      if ($toStringFirst) {\n        $toStringFirst = false\n      } else {\n        _result.append(', ')\n      }\n      _result.append('lastName:')\n      if (lastName.is(this)) {\n        _result.append('(this)')\n      } else {\n        _result.append(InvokerHelper.toString(lastName))\n      }\n    }\n    _result.append(')')\n    return _result.toString()\n  }\n\n}\n\ndef nancy = new SleuthExpanded(firstName: 'Nancy', lastName: 'Drew')\nassert nancy.toString() == 'Sleuth(firstName:Nancy, lastName:Drew)'\nnancy.lastName = null\nassert nancy.toString() == 'Sleuth(firstName:Nancy)'\n"
  },
  {
    "path": "listings/chap09/snippet0903_greeterExpanded.txt",
    "content": "class Greeter {\n  def greet() {\n    println \"Hello from the greet() method!\"\n  }\n\n  public static void main(String[] args) {\n    new Greeter().greet()\n  }\n}\n"
  },
  {
    "path": "listings/chap09/snippet0903_greeterScript.txt",
    "content": "class Greeter {\n  @Main\n  def greet() {\n    println \"Hello from the greet() method!\"\n  }\n}\n"
  },
  {
    "path": "listings/chap09/snippet0903_localMain.txt",
    "content": "@Retention(RetentionPolicy.SOURCE)\n@Target([ElementType.METHOD])\n@GroovyASTTransformationClass(classes = [MainTransformation])\n@interface Main {}\n"
  },
  {
    "path": "listings/chap09/snippet0903_localMainTransformation.txt",
    "content": "@GroovyASTTransformation(phase = CompilePhase.INSTRUCTION_SELECTION)\nclass MainTransformation implements ASTTransformation {\n  void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {\n    // perform any checks\n    // construct appropriate main method\n    // add main method to class\n  }\n}\n"
  },
  {
    "path": "listings/chap09/snippet0905_GetCompiledTimeScript.txt",
    "content": "println 'script compiled at: ' + compiledTime\nclass MyClass { }\nprintln 'script class compiled at: ' + MyClass.compiledTime\n"
  },
  {
    "path": "listings/chap09/src/main/groovy/regina/CompiledAtASTTransformation.groovy",
    "content": "package regina\n\nimport org.codehaus.groovy.ast.*\nimport org.codehaus.groovy.transform.*\nimport org.codehaus.groovy.control.*\nimport org.codehaus.groovy.ast.builder.AstBuilder\nimport static groovyjarjarasm.asm.Opcodes.*\n\n@GroovyASTTransformation(phase=CompilePhase.CONVERSION)\nclass CompiledAtASTTransformation implements ASTTransformation {\n\n  private static final compileTime = new Date().toString()\n\n  void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {\n    List classes = sourceUnit.ast?.classes\n    classes.each { ClassNode clazz ->\n      clazz.addMethod(makeMethod())\n    }\n  }\n\n  MethodNode makeMethod() {\n    def ast = new AstBuilder().buildFromSpec {\n      method('getCompiledTime', ACC_PUBLIC | ACC_STATIC, String) {\n        parameters {}\n        exceptions {}\n        block {\n          returnStatement {\n            constant(compileTime)\n          }\n        }\n        annotations {}\n      }\n    }\n    ast[0]\n  }\n}\n"
  },
  {
    "path": "listings/chap09/src/main/resources/META-INF/services/org.codehaus.groovy.transform.ASTTransformation",
    "content": "regina.CompiledAtASTTransformation"
  },
  {
    "path": "listings/chap09/src/test/groovy/regina/CompiledAtASTTransformationTest.groovy",
    "content": "package regina\n\nclass CompiledAtASTTransformationTest extends GroovyTestCase {\n  // matches format: EEE MMM dd HH:mm:ss zzz yyyy\n  static DATE_FMT = /\\w{3} \\w{3} \\d\\d \\d\\d:\\d\\d:\\d\\d \\S{3,9} \\d{4}/\n\n  @Override\n  protected void setUp() throws Exception {\n    super.setUp()\n  }\n\n  void testShouldApplyToThisTest() {\n    assert compiledTime.toString() =~ DATE_FMT\n  }\n\n  void testShouldApplyToScriptAndScriptClasses() {\n    assertScript '''\n      import static regina.CompiledAtASTTransformationTest.*\n      assert compiledTime.toString() =~ DATE_FMT\n      class MyClass { }\n      assert MyClass.compiledTime.toString() =~ DATE_FMT\n    '''\n  }\n}\n"
  },
  {
    "path": "listings/chap10/Greeter.java",
    "content": "public class Greeter {               // Java!\n    static void greet(Object o) {\n        System.out.println(\"Hello, object \" + o);\n    }\n\n    static void greet(String s) {\n        System.out.println(\"Hello, string \" + s);\n    }\n\n    public static void main(String... args) {\n        Object o = \"Bob\";\n        String s = \"Bob\";\n        greet(o);\n        greet(s);\n    }\n}\n\n"
  },
  {
    "path": "listings/chap10/Listing_10_01_Duck.groovy",
    "content": "class Duck {\n  def methodMissing(String name, args) {\n    println \"$name!\"\n  }\n}\n\ndef duck = new Duck()\nduck.quack()\n"
  },
  {
    "path": "listings/chap10/Listing_10_02_failing_Typo.groovy",
    "content": "class Detective {\n  String firstName\n  String lastName\n}\n\ndef sherlock = new Detective(firstname: 'Sherlock', lastname: 'Holmes')\n\n\nassert sherlock.lastName == 'Holmes'\n"
  },
  {
    "path": "listings/chap10/Listing_10_03_ClassTC.groovy",
    "content": "import groovy.transform.TypeChecked\n\n@TypeChecked                                                  //#A\nclass Sleuth {\n  String firstName\n  String lastName\n\n  String getFullName() { \"$firstName $lastName\" }\n}\n\nassert new Sleuth(firstName: 'Nancy',\n                   lastName: 'Drew').fullName == 'Nancy Drew'\n//#A Class annotation"
  },
  {
    "path": "listings/chap10/Listing_10_04_OneMethodTC.groovy",
    "content": "import groovy.transform.TypeChecked\n\nclass Actor {\n  String firstName, lastName\n\n  @TypeChecked\n  String getFullName() { \"$firstName $lastName\" }         //#1\n\n  void makePeace() {\n    new AntBuilder().echo('Peace was never an option')    //#2\n  }\n}\n\ndef magneto = new Actor(firstName: 'Ian', lastName: 'McKellen')\nassert magneto.fullName == 'Ian McKellen'\nmagneto.makePeace()\n//#1 Checked\n//#2 Dynamic features allowed\n"
  },
  {
    "path": "listings/chap10/Listing_10_05_CompileTimeTypo.groovy",
    "content": "import static groovy.test.GroovyAssert.shouldFail\n\ndef e = shouldFail '''\nimport groovy.transform.TypeChecked\n\n@TypeChecked\nclass Sleuth {\n  String firstName\n  String lastName                                        //#A\n  String getFullName() { \"$firstName $lastname\" }        //#B\n}\n'''.trim()\nprintln e.message\nassert e.message.contains(\n    '[Static type checking] - The variable [lastname] is undeclared')\n//#A Uppercase N in lastName\n//#B Incorrect lowercase n in lastname\n"
  },
  {
    "path": "listings/chap10/Listing_10_06_MethodNameTypo.groovy",
    "content": "import static groovy.test.GroovyAssert.shouldFail\n\ndef e = shouldFail '''\n@groovy.transform.TypeChecked\nclass Person {\n  String name\n  String getFullName() { name.toUppercase() }        //#A\n}\n'''\nprintln e.message\nassert e.message.contains(\n    'Cannot find matching method java.lang.String#toUppercase()')\n//#A Incorrect lowercase c\n"
  },
  {
    "path": "listings/chap10/Listing_10_07_MethodArgsFlipped.groovy",
    "content": "import static groovy.test.GroovyAssert.shouldFail\n\ndef e = shouldFail '''\n@groovy.transform.TypeChecked\nclass Repeat {\n    static void repeat(int n, String message) {\n        n.times{ println message }\n    }\n    static void validateAll(String... args) {\n        repeat('Hello', 4)\n    }\n}\n'''\nprintln e.message\nassert e.message.contains(\n    'Cannot find matching method Repeat#repeat(java.lang.String, int)')\n"
  },
  {
    "path": "listings/chap10/Listing_10_08_InvalidAssignments.groovy",
    "content": "import static groovy.test.GroovyAssert.shouldFail\n\ndef e = shouldFail '''\n@groovy.transform.TypeChecked\nvoid testAssignmentsShouldThrowCompilationErrors() {\n  Set set = new Object()                              //#A\n  byte b = 200L                                       //#B\n  List<Integer> list = ['Richard', 'Mary']            //#C\n  int prim = null                                     //#D\n}\n'''\n// massage to account for error message typo fixed in 2.4.1\ndef message = e.message.replaceAll('loose of precision', 'loss of precision')\n[\n  'Cannot assign value of type java.lang.Object to variable of ' +\n      'type java.util.Set',\n    // typo loose should be loss in 2.4.1\n  'Possible loss of precision from long to byte',\n  'Incompatible generic argument types. Cannot assign ' +\n      'java.util.List <java.lang.String> to: java.util.List <Integer>',\n  'Cannot assign value of type java.lang.Object to variable of type int'\n].each{ assert message.contains(it) }\n//#A Cannot cast Object into Set\n//#B Possible loss of precision\n//#C Wrong generics\n//#D Primitives cannot be null\n"
  },
  {
    "path": "listings/chap10/Listing_10_09_AssignmentsWithCoercion.groovy",
    "content": "enum MyEnum {\n    var, val\n}\n\n@groovy.transform.TypeChecked\nvoid testAssignmentsWithCoercion() {\n    MyEnum val = 'val'                              //#A\n    assert val == MyEnum.val\n\n    String blue = java.awt.Color.BLUE               //#B\n    assert blue == 'java.awt.Color[r=0,g=0,b=255]'\n\n    boolean nonEmpty = new Date()                   //#C\n    Boolean empty = ''                              //#C\n    assert nonEmpty\n    assert !empty\n\n    Class stringClass = 'java.lang.String'          //#D\n    assert stringClass.interfaces.size() == 3\n}\n\ntestAssignmentsWithCoercion()\n//#A Strings coerced to enum values\n//#B Anything coerced to String\n//#C Anything coerced to boolean/Boolean\n//#D Strings coerced to classes\n"
  },
  {
    "path": "listings/chap10/Listing_10_10_DefField.groovy",
    "content": "class Holder {\n  def value = 'My value'                    //#1\n}\n\n@groovy.transform.TypeChecked\nvoid testNoCompileTimeErrorDueToDef() {\n  def holder = new Holder()                 //#2\n  holder.value = 5                          //#3\n}\n\ntestNoCompileTimeErrorDueToDef()\n//#1 Property declaration\n//#2 Create Holder instance\n//#3 Holder value type changes!\n"
  },
  {
    "path": "listings/chap10/Listing_10_11_InPlaceList.groovy",
    "content": "def authors = ['Dierk', 'Guillaume']               //#1\nauthors.each { println it }                        //#A\n//#1 Declaration of a list\n//#A List iteration\n"
  },
  {
    "path": "listings/chap10/Listing_10_12_Generics.groovy",
    "content": "import groovy.transform.TypeChecked\n\n@TypeChecked\nvoid printAuthors() {\n  def authors = ['Dierk', 'Guillaume']\n  printToUpperCase(authors)\n}\n\nvoid printToUpperCase(List<String> authors) {\n  authors.each { println it.toUpperCase() }\n}\n\nprintAuthors()\n"
  },
  {
    "path": "listings/chap10/Listing_10_13_ListStyleCtorRuntime.groovy",
    "content": "import static groovy.test.GroovyAssert.shouldFail\n\nvoid oneDimensional() {\n    java.awt.Dimension d = [100]              //#A\n}\n\nshouldFail(ClassCastException) {\n    oneDimensional()\n}\n//#A Two parameters required! Runtime error here!\n"
  },
  {
    "path": "listings/chap10/Listing_10_14_ListStyleCtorTC.groovy",
    "content": "import org.codehaus.groovy.control.CompilationFailedException\nimport static groovy.test.GroovyAssert.shouldFail\n\ndef e = shouldFail CompilationFailedException, '''\n    @groovy.transform.TypeChecked\n    void alsoOneDimensional() {\n        java.awt.Dimension d = [100]              //#A\n    }\n'''\nassert e.message.contains(\n    'No matching constructor found: java.awt.Dimension<init>(int)')\n//#A Two parameters required. Compilation fails!\n"
  },
  {
    "path": "listings/chap10/Listing_10_15_MapStyleCtorBad.groovy",
    "content": "import static groovy.test.GroovyAssert.shouldFail\n\ndef e = shouldFail '''\nimport groovy.transform.TypeChecked\n\nclass Athlete {\n  String first\n  String last\n  int age\n}\n\n@TypeChecked\nvoid ageInteger() {\n  Athlete ok = [first: 'Michael', last: 'Jordan', age: 52]          //#A\n}\n\n@TypeChecked\nvoid ageString() {\n  Athlete bad = [first: 'Michael', last: 'Jordan', age: '52']       //#B\n}\n\n@TypeChecked\nvoid ageStringNormal() {\n  def alsoBad =\n      new Athlete(first: 'Michael', last: 'Jordan', age: '52')      //#B\n}\n//#A Passes\n//#B Fails\n'''\nassert e.message.contains(\n    'Cannot assign value of type java.lang.String to variable of type int')\n"
  },
  {
    "path": "listings/chap10/Listing_10_16_ListStyleCtor.groovy",
    "content": "import static groovy.test.GroovyAssert.shouldFail\n\ndef e = shouldFail '''\nimport groovy.transform.*\n\n@TupleConstructor\nclass Author {\n    String first\n    String last\n    int born\n}\n\n@TypeChecked\nAuthor createAuthor(List params) {\n    Author a = params                //#A\n    a\n}\ncreateAuthor(['Agatha', 'Christie', 1890])\n'''\nassert e.message.contains('Cannot assign value of type java.util.List' +\n    ' to variable of type Author')\n//#A Compile-time error!\n"
  },
  {
    "path": "listings/chap10/Listing_10_17_ListStyleCtorFixed.groovy",
    "content": "import groovy.transform.*\n\n@TupleConstructor\nclass Author {\n  String first\n  String last\n  int born\n}\n\n@TypeChecked\nAuthor createAuthor(List params) {\n  if (params.size() != 3) {\n    throw new IllegalArgumentException('Incorrect number of arguments')\n  }\n  String first = params[0]                      //#A\n  String last = params[1]                       //#A\n  Integer age = (Integer) params[2]             //#B\n  Author a = [first, last, age]                 //#C\n  a\n}\n\nassert createAuthor(['Agatha', 'Christie', 1890]).born == 1890\n//#A no need to cast as String on LHS\n//#B Cast required\n//#C Passes\n"
  },
  {
    "path": "listings/chap10/Listing_10_18_CodeAsData.groovy",
    "content": "def sum1(int x, int y) { x + y }                //#1\ndef sum2 = { int x, int y -> x + y }            //#2\nassert sum1(3, 4) == 7\nassert sum2(4, 5) == 9\n//#1 sum function defined using a method\n//#2 sum function defined using a closure\n"
  },
  {
    "path": "listings/chap10/Listing_10_19_ClosuresBadReturnType.groovy",
    "content": "import static groovy.test.GroovyAssert.shouldFail\n\ndef e = shouldFail '''\nimport groovy.transform.TypeChecked\n\nclass Logger {\n  static void print(Closure<String> messageProvider) {\n    println \"Received message : ${messageProvider()}\"\n  }\n}\n\n@TypeChecked\nvoid testMessage() {\n  def returnsString = { 'Hello, Groovy!' }\n  def returnsInt = { int x, int y -> x + y }\n  Logger.print(returnsString)            //#1\n  Logger.print(returnsInt)               //#2\n}\n'''\nprintln e.message.readLines().find{ it.contains('[Static ') }\nassert e.message.contains(\n    'Cannot call Logger#print(groovy.lang.Closure <java.lang.String>)' +\n        ' with arguments [groovy.lang.Closure <java.lang.Integer>]')\n//#1 Passes\n//#2 Compilation fails\n"
  },
  {
    "path": "listings/chap10/Listing_10_20_UserValidation.groovy",
    "content": "void validate(User u, Closure<Boolean> rule) {\n  if (!rule.call(u)) {                                              //#1\n    println \"User $u.name $u.password rejected\"\n  }\n}\n\nvoid validateAll(user) {\n  validate(user) { !it.name.isEmpty() }                             //#2\n  validate(user) { it.password.size() > 7 }                         //#3\n}\n\ndef bob = new User(name: 'Bob', password: 'secr3t')\nvalidateAll(bob)\n//#1 Apply rule\n//#2 Example passing rule\n//#3 Example failing rule\n"
  },
  {
    "path": "listings/chap10/Listing_10_21_UserValidationTC.groovy",
    "content": "import static groovy.test.GroovyAssert.shouldFail\n\ndef e = shouldFail '''\nclass User { String name, password }\n\nimport groovy.transform.TypeChecked\n\nvoid validate(User u, Closure<Boolean> rule) {\n  if (!rule.call(u)) {\n    println \"User $u.name $u.password rejected\"\n  }\n}\n\n@TypeChecked\nvoid validateAll(user) {                           //#1\n  validate(user) { !it.name.isEmpty() }            //#2\n  validate(user) { it.password.size() > 7 }        //#3\n}\n\ndef bob = new User(name: 'Bob', password: 'secr3t')\nvalidateAll(bob)\n'''\n// println out just the error messages\nprintln e.message.readLines().findAll{ it.contains('[Static type checking]') }*.replaceAll(/.*(\\[Static type checking\\])(.*)/, '$1$2').join('\\n')\nassert e.message.contains('No such property: name for class: java.lang.Object')\nassert e.message.contains('No such property: password for class: java.lang.Object')\nassert e.message =~ /Cannot find matching method.*validate\\(java.lang.Object, groovy.lang.Closure\\)/\n//#1 Type of user is Object\n//#2 No property name for Object\n//#3 No property password for Object\n"
  },
  {
    "path": "listings/chap10/Listing_10_22_UserValidation_ExplicitTypes.groovy",
    "content": "import groovy.transform.TypeChecked\n\nvoid validate(User u, Closure<Boolean> rule) {\n  if (!rule.call(u)) {\n    println \"User $u.name $u.password rejected\"\n  }\n}\n\n@TypeChecked\nvoid validateAll(User user) {                           //#A\n  validate(user) { User u -> !u.name.isEmpty() }        //#A\n  validate(user) { User u -> u.password.size() > 7 }    //#A\n}\n\ndef bob = new User(name: 'Bob', password: 'secr3t')\nvalidateAll(bob)\n//#A User type in method and closure declarations\n"
  },
  {
    "path": "listings/chap10/Listing_10_23_UserValidation_SAM.groovy",
    "content": "import groovy.transform.TypeChecked\n\ninterface Predicate<On> { boolean apply(On e) }          //#1\n\nvoid validate(User u, Predicate<User> rule) {            //#2\n  if (!rule.apply(u)) {\n    println \"User $u.name $u.password rejected\"\n  }\n}\n\n@TypeChecked\nvoid validateAll(User user) {\n  validate(user) { !it.name.isEmpty() }            //#3\n  validate(user) { it.password.size() > 7 }        //#3\n}\n\ndef bob = new User(name: 'Bob', password: 'secr3t')\nvalidateAll(bob)\n//#1 SAM type definition\n//#2 SAM type argument\n//#3 Implicit type inferred\n"
  },
  {
    "path": "listings/chap10/Listing_10_24_UserValidation_ClosureParams.groovy",
    "content": "import groovy.transform.TypeChecked\nimport groovy.transform.stc.*\n\nvoid validate(User u,\n              @ClosureParams(FirstParam) Closure<Boolean> rule) {   //#1\n  if (!rule.call(u)) {\n    println \"User $u.name $u.password rejected\"\n  }\n}\n\n@TypeChecked\nvoid validateAll(User user) {\n  validate(user) { !it.name.isEmpty() }\n  validate(user) { it.password.size() > 7 }\n}\n\ndef bob = new User(name: 'Bob', password: 'secr3t')\nvalidateAll(bob)\n"
  },
  {
    "path": "listings/chap10/Listing_10_25_UserValidation_DSL.groovy",
    "content": "def validate(User u, Closure rule) {\n  rule.delegate = u                                                 //#1\n  rule()                                                            //#2\n}\n\nvoid validateAll(User u) {\n  validate(u) { if (name.isEmpty()) println 'Empty name' }             //#3\n  validate(u) { if (password.size() < 8) println 'Password too short' }//#3\n}\n\ndef bob = new User(name: 'Bob', password: 'secr3t')\nvalidateAll(bob)\n//#1 Set user as delegate\n//#2 Call validation rule\n//#3 Simplified rule syntax\n"
  },
  {
    "path": "listings/chap10/Listing_10_26_UserValidation_DelegatesTo.groovy",
    "content": "import groovy.transform.TypeChecked\n\ndef validate(User u, @DelegatesTo(User) Closure rule) {        //#A\n  rule.delegate = u\n  rule()\n}\n\n@TypeChecked\nvoid validateAll(User u) {\n  validate(u) { if (name.isEmpty()) println 'Empty name' }\n  validate(u) { if (password.size() < 8) println 'Password too short' }\n}\n\ndef bob = new User(name: 'Bob', password: 'secr3t')\nvalidateAll(bob)\n//#A Annotation on Closure parameter\n"
  },
  {
    "path": "listings/chap10/Listing_10_27_UserValidation_DelegatesToTarget.groovy",
    "content": "import groovy.transform.TypeChecked\n\ndef validate(@DelegatesTo.Target User u, @DelegatesTo Closure rule) { //#A\n  rule.delegate = u\n  rule()\n}\n\n@TypeChecked\nvoid validateAll(User u) {\n  validate(u) { if (name.isEmpty()) println 'Empty name' }\n  validate(u) { if (password.size() < 8) println 'Password too short' }\n}\n\ndef bob = new User(name: 'Bob', password: 'secr3t')\nvalidateAll(bob)\n//#A Annotate the Closure and the User\n"
  },
  {
    "path": "listings/chap10/Listing_10_28_Category.groovy",
    "content": "import groovy.time.TimeCategory\n\nclass VacationHelper {\n    static duration() {\n        use(TimeCategory) {\n            doCompute()\n        }\n    }\n\n    static doCompute() { 1.week - 1.day }\n}\n\nassert VacationHelper.duration().toString() == '6 days'\n"
  },
  {
    "path": "listings/chap10/Listing_10_29_EMC.groovy",
    "content": "class Spy {\n    static {\n        def mc = new ExpandoMetaClass(Spy, false, true)             //#A\n        mc.initialize()\n        Spy.metaClass = mc\n    }\n    String name = \"James\"\n\n    void methodMissing(String name, args) {\n        if (name.startsWith('changeNameTo')) {\n            println \"Adding method $name\"\n            String newName = name.substring(12)\n            def newMethod = { delegate.name = newName }             //#1\n            Spy.metaClass.\"$name\" = newMethod                       //#2\n            newMethod()                                             //#B\n        } else {\n            throw new MissingMethodException(name, this.class, args)\n        }\n    }\n}\n\ndef spy = new Spy()\nassert \"James\" == spy.name\nspy.changeNameToAustin()\nassert \"Austin\" == spy.name\nspy.changeNameToMaxwell()\nassert \"Maxwell\" == spy.name\nspy.changeNameToAustin()\n//#1 If method not found, define new one\n//#2 Cache method\n//#A Create an ExpandoMetaClass for Spy class\n//#B Call new method\n"
  },
  {
    "path": "listings/chap10/Listing_10_30_Builder.groovy",
    "content": "import groovy.xml.MarkupBuilder\n\ndef writer = new StringWriter()\ndef xml = new MarkupBuilder(writer)        //#A\n\nxml.html {                            //#1\n   head {                             //#1\n       title('An XHTML Page')         //#1\n   }\n}\n\nprintln writer\n//#A Instantiate MarkupBuilder\n//#1 Method calls that @TypeChecked would reject\n"
  },
  {
    "path": "listings/chap10/Listing_10_31_MixedTypeChecking.groovy",
    "content": "import groovy.xml.MarkupBuilder\nimport groovy.transform.TypeChecked\n\nclass HTMLExample {\n    private static String buildPage(String pageTitle) {\n        def writer = new StringWriter()\n        def xml = new MarkupBuilder(writer)\n\n        xml.html {\n           head { title(pageTitle) }\n        }\n        writer\n    }\n\n    @TypeChecked                                     //#A\n    static String page404() {\n        buildPage '404 - Not Found'\n    }\n}\n\nHTMLExample.page404()\n//#A Type check only this method\n"
  },
  {
    "path": "listings/chap10/Listing_10_32_Skip.groovy",
    "content": "import groovy.xml.MarkupBuilder\nimport groovy.transform.TypeChecked\nimport groovy.transform.TypeCheckingMode\n\n@TypeChecked                                                     //#A\nclass HTMLExample2 {\n    @TypeChecked(TypeCheckingMode.SKIP)                          //#B\n    private static String buildPage(String pageTitle) {\n        def writer = new StringWriter()\n        def xml = new MarkupBuilder(writer)\n\n        xml.html {\n           head { title(pageTitle) }\n        }\n        writer\n    }\n\n    static String page404() {\n        buildPage '404 - Not Found'\n    }\n}\n\nHTMLExample2.page404()\n//#A Type check class\n//#B But exclude this method\n"
  },
  {
    "path": "listings/chap10/Listing_10_33_FlowTyping.groovy",
    "content": "import static groovy.test.GroovyAssert.shouldFail\n\ndef e = shouldFail '''\nimport groovy.transform.TypeChecked\n\n@TypeChecked\ndef flowTyping() {\n    def var = 'A string'                            //#1\n    var = var.toUpperCase()                         //#2\n    var = var.length()                              //#3\n    var = String.valueOf(var)                       //#4\n    var = 2*var                                     //#5\n    var\n}\n//#1 Assign String to var\n//#2 Assign another String to var\n//#3 Assign int to var\n//#4 Assign String to var\n//#5 FAIL! Trying to call (int*String)\n'''\nprintln e.message.readLines().find{ it.contains('[Static type') }\nassert e.message.contains('Cannot find matching method int#multiply(java.lang.String)')\n"
  },
  {
    "path": "listings/chap10/Listing_10_34_FlowTypingOk.groovy",
    "content": "import groovy.transform.TypeChecked\n\ninterface Flying {\n  void fly()\n}\n\nclass Bird implements Flying {\n  void fly() { println \"I'm flying!\" }\n}\n\nclass Canary extends Bird {\n  void sing() { println \"Tweet!\" }\n}\n\n@TypeChecked\nvoid main() {\n  def o = new Bird()\n  o.fly()                        //#1\n  o = new Canary()\n  o.fly()                        //#2\n  o.sing()                       //#2\n//  o = new Bird()\n//  o.sing()                //#A\n}\n\nmain()\n//#1 a bird can fly\n//#2 a canary can fly too and also sing\n//#A Would fail compilation\n"
  },
  {
    "path": "listings/chap10/Listing_10_35_LUB.groovy",
    "content": "import static groovy.test.GroovyAssert.shouldFail\n\ndef e = shouldFail '''\nimport groovy.transform.TypeChecked\n\ninterface Polite {\n    void greet()\n    void thank()\n}\n\nclass Person implements Polite {\n    String name\n    void greet() { println \"Hello, I'm $name!\" }\n    void thank() { println 'Thanks!' }\n}\n\nclass Owl implements Polite {\n    void greet() { hoot() }\n    void thank() { hoot() }\n    void hoot() { println 'Hoot' }\n}\n\n@TypeChecked\nvoid main() {\n    def list = [new Person(name: 'Bill'), new Owl()]              //#A\n    Polite p1 = list[0]                                           //#B\n    Polite o1 = list[1]                                           //#B\n    Owl o2    = list[0]                                           //#1\n    Person p2 = list[1]                                           //#2\n// extra sample (comment out and not mentioned in the book):\n// a way to overcome above problem if we wanted to in Groovy\n//    def tuple = new Tuple2<Person, Owl>(new Person(name: 'Bill'), new Owl())\n//    Person p3 = tuple.first\n//    Owl o3 = tuple.second\n}\n\nmain()\n//#A Create list with Person and Owl\n//#B Assign either element to variable of type Polite\n//#1 Try to assign 1st element to Owl\n//#2 Try to assign 2nd element to Person\n'''\nassert e.message.contains('Cannot assign value of type Polite to variable of type Owl')\nassert e.message.contains('Cannot assign value of type Polite to variable of type Person')\n"
  },
  {
    "path": "listings/chap10/Listing_10_36_Condition.groovy",
    "content": "import static groovy.test.GroovyAssert.shouldFail\n\ndef e = shouldFail '''\nimport groovy.transform.TypeChecked\n\n@TypeChecked\nvoid leastUpperBoundOnConditional() {\n    def o = new Date()                                //#1\n    if (Math.random()) {                              //#A\n        o = 'Hello'                                   //#2\n    }\n    o.time                                            //#B\n}\n//#1 Variable initialized with Date\n//#A Random condition\n//#2 Assign a String\n//#B Try to call o.time\n'''\nassert e.message.contains('No such property: time for class: java.io.Serializable')\n"
  },
  {
    "path": "listings/chap10/Listing_10_37_ClosureSharedVar.groovy",
    "content": "import groovy.transform.TypeChecked\n\n@TypeChecked\ndef captureOfALocalVariable() {\n  def msg = 'Hello'                               //#A\n  def cl = { msg = 'Hi!' }                        //#B\n  assert msg == 'Hello'\n  cl()                                            //#1\n  assert msg == 'Hi!'\n}\n\ncaptureOfALocalVariable()\n//#A Variable msg is closure shared variable\n//#B Closure can write to msg\n//#1 Closure is called\n"
  },
  {
    "path": "listings/chap10/Listing_10_38_LubError.groovy",
    "content": "import static groovy.test.GroovyAssert.shouldFail\n\ndef e = shouldFail '''\nimport groovy.transform.TypeChecked\n\n@TypeChecked\nvoid notAllowed() {\n    def var = \"String\"\n    def cl = { var = new Date() }\n    cl()\n    var = var.toUpperCase()\n}\n'''\nassert e.message.contains(\n    'A closure shared variable [var] has been assigned with ')\n"
  },
  {
    "path": "listings/chap10/Listing_10_39_LubOk.groovy",
    "content": "import groovy.transform.TypeChecked\n\nclass A { void foo() {} }\nclass B extends A { void bar() {} }\n\n@TypeChecked\nvoid main() {\n    def var = new A()\n    def cl = { var = new B() }\n    cl()\n    var.foo()\n}\n\nmain()\n"
  },
  {
    "path": "listings/chap10/Listing_10_40_FibBench.groovy",
    "content": "@Grab('org.gperfutils:gbench:0.4.3-groovy-2.4')\nimport groovy.transform.CompileStatic\n\ndef dynamicFib(n)    { n<1 ? 1 : dynamicFib(n-1) + dynamicFib(n-2) }\n\nint primFib(int n)   { n<1 ? 1 : primFib(n-1)    + primFib(n-2)    }\n\n@CompileStatic\nint staticFib(int n) { n<1 ? 1 : staticFib(n-1)  + staticFib(n-2)  }\n\ndef r = benchmark {\n  'Dynamic Groovy'             { dynamicFib(10) }\n  'Primitive optimized Groovy' { primFib(10)    }\n  'Statically compiled Groovy' { staticFib(10)  }\n}\nr.prettyPrint()\n"
  },
  {
    "path": "listings/chap10/Listing_10_41_JavaGreeter.txt",
    "content": "see: Greeter.java\n"
  },
  {
    "path": "listings/chap10/Listing_10_42_StaticCompileDispatch.groovy",
    "content": "import groovy.transform.CompileStatic\nstatic String prettify(String s) { \"String: $s\" }\nstatic String prettify(Date d) { \"Date: ${d.time}\" }\n\n@CompileStatic\nvoid test() {\n   def var = \"I'm a String\"           //#1\n   println prettify(var)              //#2\n}\ntest()\n//#1 Using def, which is equivalent to Object\n//#2 Calls prettify(String)\n"
  },
  {
    "path": "listings/chap10/Listing_10_43_MonkeyPatching.groovy",
    "content": "import groovy.transform.CompileStatic\n\nclass MyFramework {\n  static int sizeOf(String s) { s.size() }                     //#1\n\n  @CompileStatic\n  static int staticSizeOf(String s) { s.size() }               //#2\n}\n\nString s = 'a happy new year!'\ns.metaClass.size = { -> 5 }                                    //#3\nassert s.size() == 5                                           //#4\nassert MyFramework.sizeOf(s) == 5                              //#5\nassert MyFramework.staticSizeOf(s) == 17                       //#6\n//#1 sizeOf method uses dynamic dispatch\n//#2 staticSizeOf method uses static dispatch\n//#3 change metaclass so that size always returns 5\n//#4 check that size returns 5\n//#5 check that calling size from the framework returns 5\n//#6 check that from statically compiled method returns the original size\n"
  },
  {
    "path": "listings/chap10/Listing_10_44_BookingDSL.groovy",
    "content": "import groovy.transform.Canonical\n\n@Canonical\nclass Booking {\n    String meetingRoom\n    String className\n    Date start, end\n}\n\ndef book(meeting) {\n    [room: { name ->\n        [between: { sd ->\n            [and: { ed ->\n                [to: { to ->\n                    def b = new Booking(meetingRoom: name,\n                        className: to, start: sd, end: ed)\n                    println b\n                    b\n                }]\n            }]\n        }]\n    }]\n}\n\ndef meeting\n@Category(Integer)\nclass TimeCategory {\n    static Date getAm(Integer self) {\n        def d = Calendar.instance\n        d.set(Calendar.MINUTE, 0)\n        d.set(Calendar.SECOND, 0)\n        d.set(Calendar.HOUR_OF_DAY, self)\n        d.time\n    }\n}\nuse(TimeCategory) {\n    book meeting room 'Honolulu' between 9.am and 12.am to 'B2'\n}\n\n"
  },
  {
    "path": "listings/chap10/Listing_10_45_MultiValidation.groovy",
    "content": "import groovy.transform.TypeChecked\n\nclass Address { String country }\nclass WishList { List<String> items }\n\ndef validate(@DelegatesTo.Target def o, @DelegatesTo Closure rule) { //#1\n  rule.delegate = o\n  rule()\n}\n\n@TypeChecked\nvoid validateAll() {\n  def a = new Address(country: 'Australia')\n  validate(a) {                                           //#2\n    if (country[0] == 'X')                                //#3\n      println 'No countries start with that'\n  }\n  def wl = new WishList(items: ['iphone', 'iphone'])\n  validate(wl) {                                          //#4\n    if (items != items.toUnique())                        //#5\n      println 'Some item appeared twice'\n  }\n}\n\nvalidateAll()\n//#1 Compiler will determine type\n//#2 First param is Address\n//#3 Address inferred so country will be found\n//#4 First param is WishList\n//#5 WishList inferred so items will be found\n"
  },
  {
    "path": "listings/chap10/Listing_10_46_RobotExtension.groovy",
    "content": "unresolvedVariable { var ->                                  //#1\n  if (var.name == 'robot') {                                 //#1\n    storeType(var, lookupClassNodeFor('Robot'))              //#1\n    handled = true                                           //#1\n  }\n}\n\nunresolvedProperty { pexp ->                                 //#2\n  if (getType(pexp.objectExpression) == int_TYPE &&          //#2\n      pexp.propertyAsString == 'meters') {                   //#2\n    storeType(pexp, long_TYPE)                               //#2\n    handled = true                                           //#2\n  }\n}\n//#1 An unresolved 'robot' variable has type Robot\n//#2 An unresolved 'meters' property on an int has type long"
  },
  {
    "path": "listings/chap10/Listing_10_47_SQLExtension.groovy",
    "content": "@Grab('com.github.jsqlparser:jsqlparser:0.9.2')\nimport net.sf.jsqlparser.parser.CCJSqlParserManager\n\nafterMethodCall { mc ->\n  def receiver = mc.receiver\n  if (!isVariableExpression(receiver)) return              //#1\n  def method = getTargetMethod(mc)                         //#1\n  if (classNodeFor(groovy.sql.Sql) == getType(receiver)    //#1\n      && method.name == 'eachRow') {                       //#1\n    def argList = getArguments(mc)                         //#1\n    if (argList && isConstantExpression(argList[0])) {     //#1\n\n      def pm = new CCJSqlParserManager()                        //#2\n      def sqlQuery = argList[0].text                            //#2\n      try {                                                     //#2\n        pm.parse(new StringReader(sqlQuery))                    //#2\n      } catch (e) {\n        addStaticTypeError(\"SQL query is not valid: $e\", argList[0]) //#3\n      }\n    }\n  }\n}\n//#1 Info extraction and guards\n//#2 Validate SQL using library\n//#3 Flag an error if invalid\n"
  },
  {
    "path": "listings/chap10/User.groovy",
    "content": "class User {\n  String name\n  String password\n}\n"
  },
  {
    "path": "listings/chap10/extra1004_JavaDispatch.java",
    "content": "import java.util.Date;\n\nclass JavaDispatch {\n    public static String prettify(Object o) {\n      if (o instanceof String) { return doPrettify((String) o); }\n      if (o instanceof Date) { return doPrettify((Date) o); }\n      return doPrettify(o);\n    }\n\n    static String doPrettify(Object o) { return \"Value:\"+o.toString(); }\n    static String doPrettify(String s) { return \"String:\"+s; }\n    static String doPrettify(Date d) { return \"Date:\"+d.getTime(); }\n}\n"
  },
  {
    "path": "listings/chap10/extra1004_RuntimeGroovyDispatch.groovy",
    "content": "static String prettify(String s) { \"String: $s\" }\nstatic String prettify(Date d) { \"Date: ${d.time}\" }\ndef var = \"I'm a String\"\nprintln prettify(var)\n\n"
  },
  {
    "path": "listings/chap10/markup.html",
    "content": "<html>\n  <head>\n    <title>Constructed by MarkupBuilder</title>\n  </head>\n  <body>\n    <h1>What can I do with MarkupBuilder?</h1>\n    <form action='whatever'>\n      <input type='checkbox' checked='checked' id='Produce HTML'></input>\n      <label for='Produce HTML'>Produce HTML</label>\n      <br></br>\n      <input type='checkbox' checked='checked' id='Produce XML'></input>\n      <label for='Produce XML'>Produce XML</label>\n      <br></br>\n      <input type='checkbox' checked='checked' id='Have some fun'></input>\n      <label for='Have some fun'>Have some fun</label>\n      <br></br>\n    </form>\n  </body>\n</html>"
  },
  {
    "path": "listings/chap10/snippet1003_GroovyGreeter.groovy",
    "content": "public class GroovyGreeter {\n  static void greet(Object o) {\n    System.out.println(\"Hello, object \" + o);\n  }\n\n  static void greet(String s) {\n    System.out.println(\"Hello, string \" + s);\n  }\n\n  public static void main(String... args) {\n    Object o = \"Bob\";\n    String s = \"Bob\";\n    greet(o);\n    greet(s);\n  }\n}\n"
  },
  {
    "path": "listings/chap10/snippet1005_RobotMainTC.groovy",
    "content": "import groovy.transform.TypeChecked\n\nclass Robot {\n  void move(long distance) { println \"Moving $distance meters\" }\n}\n\n@TypeChecked(extensions = 'Listing_10_46_RobotExtension.groovy')\nmain() {\n  robot.move 100.meters\n}\n\nbinding.robot = new Robot()\nInteger.metaClass.getMeters = { delegate }\nmain()\n"
  },
  {
    "path": "listings/chap10/snippet1005_SqlMainTC.groovy",
    "content": "import static groovy.test.GroovyAssert.shouldFail\n\ndef e = shouldFail '''\nimport groovy.sql.Sql\nimport groovy.transform.TypeChecked\n\n@TypeChecked(extensions = 'Listing_10_47_SQLExtension.groovy')\nfindAthletes(Sql sql) {\n  sql.eachRow('select * frm Athlete') { row -> println row }       //#A\n}\n//#A Typo 'frm' not 'from'\n'''\nprintln e.message\nassert e.message.contains('[Static type checking] - SQL query is not valid')\n"
  },
  {
    "path": "listings/chap11/Listing_11_01_SquaresFactors.xml",
    "content": "<?xml version=\"1.0\"?>\n<numbers>\n    <description>Squares and factors of 10..15</description>\n    <number value=\"10\" square=\"100\">\n        <factor value=\"2\" />\n        <factor value=\"5\" />\n    </number>\n    <number value=\"11\" square=\"121\" />\n    <number value=\"12\" square=\"144\">\n        <factor value=\"2\" />\n        <factor value=\"3\" />\n        <factor value=\"4\" />\n        <factor value=\"6\" />\n    </number>\n    <number value=\"13\" square=\"169\" />\n    <number value=\"14\" square=\"196\">\n        <factor value=\"2\" />\n        <factor value=\"7\" />\n    </number>\n    <number value=\"15\" square=\"225\">\n        <factor value=\"3\" />\n        <factor value=\"5\" />\n    </number>\n</numbers>\n"
  },
  {
    "path": "listings/chap11/Listing_11_02_SquaresFactors.java",
    "content": "import org.w3c.dom.Element;\nimport org.w3c.dom.Document;\n\npublic class Listing_11_02_SquaresFactors {\n    public void process(Document doc) {\n/////////// EXAMPLE START\n// Java!\n// … doc made available here …\nElement numbers     = doc.createElement(\"numbers\");\nElement description = doc.createElement(\"description\");\ndoc.appendChild(numbers);\nnumbers.appendChild(description);\ndescription.setTextContent(\"Squares and factors of 10..15\");\n\nfor (int i=10; i <= 15; i++)\n{\n    Element number = doc.createElement(\"number\");\n    numbers.appendChild(number);\n    number.setAttribute(\"value\",  String.valueOf(i));\n    number.setAttribute(\"square\", String.valueOf(i*i));\n    for (int j=2; j < i; j++)\n    {\n        if (i % j== 0)\n        {\n            Element factor = doc.createElement(\"factor\");\n            factor.setAttribute(\"value\", String.valueOf(j));\n            number.appendChild(factor);\n        }\n    }\n}\n////////// EXAMPLE END\n    }\n}\n"
  },
  {
    "path": "listings/chap11/Listing_11_03_MarkupBuilderPlain.groovy",
    "content": "def builder = new groovy.xml.MarkupBuilder()\nbuilder.numbers {\n\n    description 'Squares and factors of 10..15'\n\n    for (i in 10..15) {\n        number (value: i, square: i*i) {  //#1\n            for (j in 2..<i) {\n                if (i % j == 0) {\n                    factor (value: j)     //#2\n                }\n            }\n        }\n    }\n}\n//#1 Emit number elements 10 through 15\n//#2 Emit each factor element"
  },
  {
    "path": "listings/chap11/Listing_11_04_NodeBuilder.groovy",
    "content": "def builder = new NodeBuilder()                            //#1\ndef ulcDate = Date.parse('yyyy-MM-dd', \"2015-01-01\")\ndef otherDate = Date.parse('yyyy-MM-dd', '2015-02-02')\ndef invoices = builder.invoices {                          //#2\n  invoice(date: ulcDate) {                                 //#3\n    item(count: 5) {\n      product(name: 'ULC', dollar: 1499)\n    }\n    item(count: 1) {\n      product(name: 'Visual Editor', dollar: 499)\n    }\n  }\n  invoice(date: otherDate) {\n    item(count: 4) {\n      product(name: 'Visual Editor', dollar: 499)\n    }\n  }\n}\n\nsoldAt = invoices.grep {                                   //#4\n  it.item.product.any { it.'@name' == 'ULC' }              //#4\n}.'@date'                                                  //#4\nassert soldAt == [ulcDate]\n//#1 Builder creation\n//#2 Root node creation\n//#3 Invoice creation\n//#4 GPath query\n"
  },
  {
    "path": "listings/chap11/Listing_11_05_NodeBuilderLogic.groovy",
    "content": "TimeZone.default = TimeZone.getTimeZone(\"CET\")                 //#A\n\ndef builder = new NodeBuilder()\ndef invoices = builder.invoices {\n  for (day in 1..3) {                                          //#B\n    def invDate = Date.parse('yyyy-MM-dd', \"2015-01-0$day\")\n    invoice(date: invDate) {                                   //#1\n      item(count: day) {                                       //#1\n        product(name: 'ULC', dollar: 1499)                     //#1\n      }                                                        //#1\n    }                                                          //#1\n  }\n}\n\ndef writer = new StringWriter()\ninvoices.print(new PrintWriter(writer))                        //#C\n\nassert writer.toString() == \"\"\"\\\ninvoices() {\n  invoice(date:Thu Jan 01 00:00:00 CET 2015) {\n    item(count:1) {\n      product(name:'ULC', dollar:1499)\n    }\n  }\n  invoice(date:Fri Jan 02 00:00:00 CET 2015) {\n    item(count:2) {\n      product(name:'ULC', dollar:1499)\n    }\n  }\n  invoice(date:Sat Jan 03 00:00:00 CET 2015) {\n    item(count:3) {\n      product(name:'ULC', dollar:1499)\n    }\n  }\n}\n\"\"\"\n//#A Set timezone for consistent Date toString() values in test\n//#B Loop over 3 days\n//#1 Code for building a single invoice\n//#C Print to a StringWriter for testing\n"
  },
  {
    "path": "listings/chap11/Listing_11_06_MarkupBuilderLogic.groovy",
    "content": "import groovy.xml.MarkupBuilder\n\nTimeZone.default = TimeZone.getTimeZone(\"CET\")\n\ndef writer = new StringWriter()\ndef builder = new MarkupBuilder(writer)                    //#1\nbuilder.invoices {\n  for (day in 1..3) {\n    def invDate = Date.parse('yyyy-MM-dd', \"2015-01-0$day\")\n    invoice(date: invDate) {\n      item(count: day) {\n        product(name: 'ULC', dollar: 1499)\n      }\n    }\n  }\n}\n\nassert \"\\n\" + writer.toString() == \"\"\"\n<invoices>\n  <invoice date='Thu Jan 01 00:00:00 CET 2015'>\n    <item count='1'>\n      <product name='ULC' dollar='1499' />\n    </item>\n  </invoice>\n  <invoice date='Fri Jan 02 00:00:00 CET 2015'>\n    <item count='2'>\n      <product name='ULC' dollar='1499' />\n    </item>\n  </invoice>\n  <invoice date='Sat Jan 03 00:00:00 CET 2015'>\n    <item count='3'>\n      <product name='ULC' dollar='1499' />\n    </item>\n  </invoice>\n</invoices>\"\"\"\n//#1 NEW: MarkupBuilder replaces NodeBuilder"
  },
  {
    "path": "listings/chap11/Listing_11_07_MarkupBuilderHtml.groovy",
    "content": "def writer = new FileWriter('markup.html')\ndef html   = new groovy.xml.MarkupBuilder(writer)                                   \nhtml.html {\n  head {\n    title 'Constructed by MarkupBuilder'\n  }\n  body {\n    h1 'What can I do with MarkupBuilder?'\nparent {\n  mkp.yield \"Some text\"\n  child('Child text')\n  mkp.yield \"more text\"\n}\n    form (action:'whatever') {\n      for (line in ['Produce HTML','Produce XML','Have some fun']){\n        input(type:'checkbox',checked:'checked', id:line, '')\n        label(for:line, line)\n        br()\n} } } }"
  },
  {
    "path": "listings/chap11/Listing_11_08_StreamingMarkupBuilderLogic.groovy",
    "content": "def builder = new groovy.xml.StreamingMarkupBuilder()\ndef writable = builder.bind {                                        //#A\n  invoices {                                                         //#B\n    for (day in 1..3) {\n      def invDate = Date.parse('yyyy-MM-dd', \"2015-01-0$day\")\n      invoice(date: invDate) {\n        item(count: day) {\n          product(name: 'ULC', dollar: 1499)\n        }\n      }\n    }\n  }\n}\ndef result = writable.toString()                                     //#C\nassert result.startsWith(\"<invoices><invoice date='Thu Jan 01\")      //#|D\nassert result.endsWith('</invoice></invoices>')                      //#|D\n//#A The bind method introduces the markup Closure\n//#B The root node must be included in the markup\n//#C Or writable.writeTo(file)\n//#D Checking start and end of long single line\n"
  },
  {
    "path": "listings/chap11/Listing_11_09_ExampleBuild.xml",
    "content": "<project name=\"prepareBookDirs\" default=\"copy\">\n\n  <property name=\"target.dir\"   value=\"target\"/>  \n  <property name=\"chapters.dir\" value=\"chapters\"/>\n  \n  <target name=\"copy\">\n    <delete dir=\"${target.dir}\" />\n    <copy todir=\"${target.dir}\">\n      <fileset dir=\"${chapters.dir}\" \n        includes=\"*.doc\" \n        excludes=\"~*\"   />\n    </copy>\n  </target>\n</project>\n"
  },
  {
    "path": "listings/chap11/Listing_11_10_PW_SwingBuilder.groovy",
    "content": "import groovy.swing.SwingBuilder\n\nswing = new SwingBuilder()\nframe = swing.frame(title:'Password') {\n\tpasswordField(columns:10, actionPerformed: { event ->       \n        println event.source.text    \n        // any further processing is called here\n        System.exit(0)\n        }\n    )     \n}\nframe.pack()\nframe.visible = true\n"
  },
  {
    "path": "listings/chap11/Listing_11_11_Swing_Widgets.groovy",
    "content": "import groovy.swing.SwingBuilder\n\nswing = new SwingBuilder()\nframe = swing.frame(title:'Demo') {\n\tmenuBar {\n        menu('File') {\n            menuItem 'New' \n            menuItem 'Open'\n        }\n    }\n    panel {\n        label 'Label 1'\n        slider()\n        comboBox(items:['one','two','three'])\n    }    \n}\nframe.pack()\nframe.visible = true\n"
  },
  {
    "path": "listings/chap11/Listing_11_12_Swing_Layout.groovy",
    "content": "import groovy.swing.SwingBuilder\nimport java.awt.BorderLayout as BL\n\nswing = new SwingBuilder()\nframe = swing.frame(title:'Layout Demo') {\n    panel(layout: new BL()) {\n        button(constraints: BL.NORTH,  'North' )\n        button(constraints: BL.CENTER, 'Center')\n        button(constraints: BL.SOUTH,  'South' )\n        button(constraints: BL.EAST,   'East'  )\n        button(constraints: BL.WEST,   'West'  )\n    }    \n}\nframe.pack()\nframe.visible = true\n"
  },
  {
    "path": "listings/chap11/Listing_11_13_Table_Demo.groovy",
    "content": "import groovy.swing.SwingBuilder\nimport groovy.transform.Canonical\nimport javax.swing.JLabel\nimport javax.swing.JTable\nimport javax.swing.table.TableCellRenderer\nimport java.awt.Color\nimport java.awt.Component\n\nimport static java.awt.Color.*\n\n@Canonical\nclass NamedColor {\n  String name\n  Color foreground, background\n}\n\npurple = new NamedColor('Purple', WHITE, new Color(127, 0, 255))\nmediumBlue = new NamedColor('Blue', WHITE, new Color(64, 128, 255))\nbrightYellow = new NamedColor('Yellow', BLACK, YELLOW)\nbrightRed = new NamedColor('Red', BLACK, RED)\n\ndata = [\n    [name: 'Anthony', color: mediumBlue],\n    [name: 'Greg', color: brightYellow],\n    [name: 'Jeff', color: purple],\n    [name: 'Murray', color: brightRed]\n]\n\nswing = new SwingBuilder()\nframe = swing.frame(title: 'Table Demo') {\n  scrollPane {\n    table(id: 'table') {\n      tableModel(list: data) {\n        propertyColumn(header: 'Name', propertyName: 'name')\n        propertyColumn(\n            header: 'Color', propertyName: 'color', type: NamedColor  //#1\n        )\n        //closureColumn(header: 'Color', read: {it.color.name})\n      }\n    }\n  }\n}\nframe.pack()\nswing.table.setDefaultRenderer(NamedColor, new ColorRenderer())       //#2\nframe.visible = true\n\nclass ColorRenderer extends JLabel implements TableCellRenderer {     //#3\n  ColorRenderer() { opaque = true }\n\n  Component getTableCellRendererComponent(JTable table, color,\n      boolean selected, boolean focus, int row, int col) {\n    background = color.background\n    foreground = color.foreground\n    text = color.name\n    horizontalAlignment = CENTER\n    this\n  }\n}\n//#1 Model can have rich types\n//#2 Registering a renderer for a rich type\n//#3 Implementing a renderer\n"
  },
  {
    "path": "listings/chap11/Listing_11_14_Binding.groovy",
    "content": "import groovy.beans.*\nimport groovy.swing.SwingBuilder\n\nimport java.awt.event.ActionEvent\nimport java.awt.event.ActionListener\nimport java.beans.PropertyVetoException\n\nclass Person implements ActionListener {\n  @Bindable String name\n  @Vetoable int age\n\n  void actionPerformed(ActionEvent e) {\n    if (e.actionCommand == name) setAge(age + 1)\n  }\n}\n\nclass BirthdayNotifier {\n  @ListenerList List<ActionListener> listeners\n\n  def triggerBirthday(name) {\n    def event = new ActionEvent(this, 0, name)\n    fireActionPerformed(event)\n  }\n}\n\ndata = [\n    new Person(name: 'Anthony', age: 51),\n    new Person(name: 'Greg', age: 42),\n    new Person(name: 'Jeff', age: 60),\n    new Person(name: 'Murray', age: 54)\n]\n\nswing = new SwingBuilder()\nframe = swing.frame(title: 'Binding Demo') {\n  table {\n    tableModel(list: data, id: 'tableModel') {\n      propertyColumn(header: 'Name', propertyName: 'name',\n          editable: true)\n      propertyColumn(header: 'Age', propertyName: 'age',\n          type: Integer, editable: true)\n    }\n  }\n}\nframe.pack()\nframe.visible = true\n\nnotifier = new BirthdayNotifier()\ndata.each {\n  it.addPropertyChangeListener { evt ->\n    println \"$evt.newValue has replaced $evt.oldValue\"              //#1\n  }\n  it.addVetoableChangeListener { evt ->\n    if (evt.newValue < 0)                                           //#2\n      throw new PropertyVetoException(\"Can't have -ve age\", evt)    //#2\n    else                                                            //#2\n      println \"$evt.source.name now has age $evt.newValue\"          //#2\n  }\n  notifier.addActionListener(it)                                    //#3\n}\n\ntry {\n  data[0].age = -99                                                 //#4\n} catch (e) {\n  println \"Change ignored: $e.message\"\n}\ndata[1].name = 'Sam'                                                //#5\ndata[1].age = 36                                                    //#5\n\nnotifier.triggerBirthday(data[2].name)                              //#6\n\nswing.tableModel.fireTableDataChanged()\n//#1 Log when the name changes\n//#2 Log when the age change but veto -ve ages\n//#3 Listen for birthday notifications\n//#4 Attempt to trigger invalid age\n//#5 Sam replaces Greg\n//#6 Jeff has a birthday\n"
  },
  {
    "path": "listings/chap11/Listing_11_15_Plotter.groovy",
    "content": "import groovy.swing.SwingBuilder\nimport java.awt.Color \nimport java.awt.BorderLayout       as BL    //#|1\nimport javax.swing.WindowConstants as WC    //#|1\nimport javax.swing.BorderFactory   as BF    //#|1\nimport javax.swing.JOptionPane\n\nswing = new SwingBuilder()\n\npaint = swing.action(\n    name:        'Paint', \n    closure:     this.&paintGraph,          //#2\n    mnemonic:    'P',\n    accelerator: 'ctrl P'\n)\nabout = swing.action(\n    name:        'About', \n    closure:     this.&showAbout,\n    mnemonic:    'A',\n    accelerator: 'F1'\n)\n\nframe = swing.frame(title:'Plotter', \n    location:[100,100], size:[500,500],     //#3\n    defaultCloseOperation:WC.EXIT_ON_CLOSE) {\n    menuBar (){\n        menu(mnemonic:'A','Action'){\n            menuItem(action:paint)\n        }\n        glue()                              //#4\n        menu(mnemonic:'H','Help'){\n            menuItem(action:about)\n        }\n    }    \n    panel (border:BF.createEmptyBorder(6,6,6,6)) {\n        borderLayout()\n        vbox (constraints: BL.NORTH){\n            hbox {                     \n                hstrut(width:10)\n                label 'f(x) = '\n                textField(id:'function',action:paint,'Math.sin(x)')\n                button(action:paint)\n            }\n        }              \n        vbox (constraints: BL.WEST){\n            labeledSpinner('max',1d)       //#5\n            20.times { swing.vglue()}      \n            labeledSpinner('min',-1d) \n        }      \n        vbox(constraints: BL.CENTER, \n            border:BF.createTitledBorder('Function Plot')) {\n            panel(id:'canvas')\n        }            \n        hbox (constraints: BL.SOUTH){        \n            hstrut(width:10)\n            labeledSpinner('from',0d) \n            10.times { swing.hglue()}   //#6 \n            labeledSpinner('to',6.3d)\n        }       \n    }\n}\nframe.visible = true\n\n// implementation methods \n\ndef labeledSpinner(label, value){          //#7       \n    swing.label(label)\n    swing.hstrut()\n    swing.spinner(id:label, stateChanged:this.&paintGraph,\n        model:swing.spinnerNumberModel(value:value)\n    ) \n}\ndef paintGraph(event) {                     //#8\n    calc = new Dynamo(swing.function.text)    \n    gfx  = swing.canvas.graphics\n    int width  = swing.canvas.size.width\n    int height = swing.canvas.size.height\n    gfx.color  = new Color(255, 255, 150)\n    gfx.fillRect(0, 0, width, height)\n    gfx.color  = Color.blue\n    xFactor    = (swing.to.value - swing.from.value) / width\n    yFactor    = height / (swing.max.value - swing.min.value)\n    int ceiling = height + swing.min.value * yFactor\n    int lastY   = calc.f(swing.from.value) * yFactor\n    for (x in (1..width)) {                  //#9\n        int y = calc.f(swing.from.value + x * xFactor) * yFactor\n        gfx.drawLine(x-1, ceiling-lastY, x, ceiling-y)\n        lastY = y\n    }\n} \nvoid showAbout(event) {                     //#10\n    JOptionPane.showMessageDialog(frame, \n'''A Function Plotter\nthat serves as a SwingBuilder example for\nGroovy in Action''')\n}\n// Keep all dynamic invocation handling in one place.\nclass Dynamo {                              \n    static final GroovyShell SHELL = new GroovyShell()\n    Script functionScript\n    Dynamo(String function){\n        functionScript = SHELL.parse(function)  //#11\n    }\n    Object f(x) {\n        functionScript.x = x\n        return functionScript.run()             //#12\n    }\n}\n//#1 type aliases as shortcuts\n//#2 refer to method closure\n//#3 general constructor\n//#4 separate help menu\n//#5 use factory method\n//#6 build with logic\n//#7 factory method\n//#8 method used as closure\n//#9 main plotting loop\n//#10 show message dialog\n//#11 once per paint\n//#12 for each x\n"
  },
  {
    "path": "listings/chap11/Listing_11_16_Groovyfx.groovy",
    "content": "@Grab('org.codehaus.groovyfx:groovyfx:0.3.1')\n\nimport static groovyx.javafx.GroovyFX.start\n\nstart {\n  stage title: 'GroovyFX Hello World', visible: true, {\n    scene fill: BLACK, width: 600, height: 300, {\n      hbox padding: 40, alignment:'center', {\n        text 'Hello', font: '80pt sanserif', {\n          fill linearGradient(endX: 0, stops: [PALEGREEN, SEAGREEN])\n        }\n        text ' FX ', font: '80pt sanserif', {\n          fill   linearGradient(endX: 0, stops: [CYAN, DODGERBLUE])\n          effect dropShadow(color: DODGERBLUE, radius: 25, spread: 0.35)\n        }\n        imageView 'file:World.png', effect:reflection()\n      }\n    }\n  }\n}"
  },
  {
    "path": "listings/chap11/Listing_11_17_CalorieCounterBuilderSupport.groovy",
    "content": "class CalorieBuilder1 extends BuilderSupport {\n  def calories = 0.0\n  def name = 'root'\n  def calorieDatabase = [\n      crust    : [thin: 169, classic: 212, deepdish: 259, stuffed: 360],\n      topping  : [pepperoni: 24, veggies: 10, cheese: 50],\n      appetizer: [wings: 60, 'garlic-bread': 180]\n  ]\n\n  def createNode(name) {\n    [name: name, calories: 0.0]\n  }\n\n  def createNode(name, value) {\n    def result = createNode(name) + [value: value]\n    findCalories(result, name, value)                      //#1\n    result\n  }\n\n  def createNode(name, Map attributes) {\n    createNode(name) + [*: attributes]\n  }\n\n  def createNode(name, Map attributes, value) {\n    createNode(name, value) + [*: attributes]\n  }\n\n  void setParent(parent, child) {\n    if (child.size && parent.size && child.size != parent.size) //#2\n      throw new IllegalStateException(\"Conflicting sizes found\")\n    if (child.size) {\n      child.scale = (child.size == 'large') ? 1.5 : 1.0\n    }\n  }\n\n  void nodeCompleted(parentOrNull, node) {\n    def parent = parentOrNull ?: this\n    def qty = node.quantity ?: 1\n    def scale = node.scale ?: 1.0\n    findCalories(node, parent.name, node.name)             //#3\n    parent.calories += node.calories * qty * scale\n  }\n\n  private void findCalories(Map map, name, value) {\n    if (calorieDatabase.containsKey(name)) {\n      map.calories = calorieDatabase[name][value].toInteger()\n    }\n  }\n\n  }\n\ndef lunch = new CalorieBuilder1()\n\nlunch.count {\n  pizza(size: 'large') {\n    crust('thin')\n    topping('pepperoni')\n    topping('veggies')\n  }\n  appetizer {\n    wings(quantity: 2)\n    'garlic-bread'()\n  }\n}\n\nassert lunch.calories == 604.5\n//#1 Handle cases like crust('thin')\n//#2 Check consistency between child and parent\n//#3 Handle cases like appetizer { wings() }\n"
  },
  {
    "path": "listings/chap11/Listing_11_18_CalorieCounterFactoryBuilderSupport.groovy",
    "content": "class CalorieBuilder2 extends FactoryBuilderSupport {\n  def calories = 0.0\n  def factory = new CalorieBeanFactory(getClass().classLoader)\n\n  protected void postInstantiate(name, Map attrs, node) {\n    super.postInstantiate(name, attrs, node)\n    attrs.each { k, v -> node[k] = v }\n  }\n\n  protected Factory resolveFactory(name, Map attrs, value) {\n    return factory\n  }\n\n  void setParent(parent, child) {\n    if (child.hasProperty(\"size\")) {\n      child.scale = child.size == 'large' ? 1.5 : 1.0\n    }\n  }\n\n  void nodeCompleted(parentOrNull, node) {\n    def parent = parentOrNull ?: this\n    def qty = node.quantity ?: 1\n    def scale = node.scale ?: 1.0\n    parent.calories += node.calories * qty * scale\n  }\n}\n\nclass CalorieBeanFactory extends AbstractFactory {\n  private ClassLoader loader\n\n  CalorieBeanFactory(ClassLoader loader) {\n    this.loader = loader\n  }\n\n  def newInstance(FactoryBuilderSupport fbs, name, value, Map attrs) {\n    def className = name[0].toUpperCase() +\n        name[1..-1].replaceAll(/-(.)/) { it[1].toUpperCase() }\n    def clazz = loader.loadClass(className)\n    return value ? clazz.newInstance(value: value) : clazz.newInstance()\n  }\n}\n\nclass Countable {\n  int quantity\n  def scale\n  def calories = 0.0\n}\n\nclass Count extends Countable {}\n\nclass Pizza extends Countable {\n  def size\n}\n\nabstract class CountableGroup extends Countable {\n  String value\n\n  abstract getCalorieDB()\n\n  def getCalories() { calorieDB[value] }\n}\n\nclass Crust extends CountableGroup {\n  def calorieDB = [thin: 169, classic: 212, deepdish: 259, stuffed: 360]\n}\n\nclass Topping extends CountableGroup {\n  def calorieDB = [pepperoni: 24, veggies: 10, cheese: 50]\n}\n\nclass Appetizer extends Countable {}\n\nclass Wings extends Countable {\n  def calories = 60\n}\n\nclass GarlicBread extends Countable {\n  def calories = 180\n}\n\ndef lunch = new CalorieBuilder2()\n\nlunch.count {\n  pizza(size: 'large') {\n    crust('thin')\n    topping('pepperoni')\n    topping('veggies')\n  }\n  appetizer {\n    wings(quantity: 2)\n    'garlic-bread'()\n  }\n}\n\nassert lunch.calories == 604.5\n"
  },
  {
    "path": "listings/chap11/Listing_11_19_CalorieCounterByHand.groovy",
    "content": "class CalorieBuilder3 {\n  def calorieDatabase = [\n      crust    : [thin: 169, classic: 212, deepdish: 259, stuffed: 360],\n      topping  : [pepperoni: 24, veggies: 10, cheese: 50],\n      appetizer: [wings: 60, 'garlic-bread': 180]\n  ]\n  def parent = new Stack()\n  def getCalories() { parent.peek().calories }\n\n  CalorieBuilder3() {\n    parent.push([calories:0.0])\n  }\n\n  def invokeMethod(String methodName, args) {\n    def current = [name: methodName, calories:0.0]\n    if (args && args[0] instanceof Map) {\n      current << args[0]\n    }\n    countCalories(current, parent.peek().name, methodName)\n    if (args && args[0] instanceof String) {\n      countCalories(current, methodName, args[0])\n    }\n    if (args && args.size() > 1 && args[1] instanceof String) {\n      countCalories(current, methodName, args[1])\n    }\n    current.scale = current.size == 'large' ? 1.5 : 1.0\n\n    if (args && args[-1] instanceof Closure) {\n      parent.push(current)\n      Closure nested = args[-1]\n      nested.delegate = this\n      nested.call()\n      parent.pop()\n    }\n    def qty = current.quantity ?: 1\n    def scale = current.scale ?: 1.0\n    parent.peek().calories += current.calories * qty * scale\n  }\n\n  private void countCalories(Map current, String key, String value) {\n    if (calorieDatabase.containsKey(key)) {\n      current.calories = calorieDatabase[key][value].toInteger()\n    }\n  }\n}\n\ndef lunch = new CalorieBuilder3()\n\nlunch.count {\n  pizza(size: 'large') {\n    crust('thin')\n    topping('pepperoni')\n    topping('veggies')\n  }\n  appetizer {\n    wings(quantity: 2)\n    'garlic-bread'()\n  }\n}\n\nassert lunch.calories == 604.5\n"
  },
  {
    "path": "listings/chap11/markup.html",
    "content": "<html>\n  <head>\n    <title>Constructed by MarkupBuilder</title>\n  </head>\n  <body>\n    <h1>What can I do with MarkupBuilder?</h1>\n    <parent>Some text\n      <child>Child text</child>more text\n    </parent>\n    <form action='whatever'>\n      <input type='checkbox' checked='checked' id='Produce HTML'></input>\n      <label for='Produce HTML'>Produce HTML</label>\n      <br />\n      <input type='checkbox' checked='checked' id='Produce XML'></input>\n      <label for='Produce XML'>Produce XML</label>\n      <br />\n      <input type='checkbox' checked='checked' id='Have some fun'></input>\n      <label for='Have some fun'>Have some fun</label>\n      <br />\n    </form>\n  </body>\n</html>"
  },
  {
    "path": "listings/chap11/snippet1103_MarkupBuilderOutput.html",
    "content": "<html>\n<head>\n    <title>Constructed by MarkupBuilder</title>\n</head>\n<body>\n<h1>What can I do with MarkupBuilder?</h1>\n<form action='whatever'>\n    <input checked='checked' type='checkbox' id='Produce HTML'/>\n    <label for='Produce HTML'>Produce HTML</label>\n    <br/>\n    <input checked='checked' type='checkbox' id='Produce XML'/>\n    <label for='Produce XML'>Produce XML</label>\n    <br/>\n    <input checked='checked' type='checkbox' id='Have some fun'/>\n    <label for='Have some fun'>Have some fun</label>\n    <br/>\n</form>\n</body>\n</html>\n"
  },
  {
    "path": "listings/chap11/snippet1103_MarkupWithHyphen.groovy",
    "content": "def writer = new StringWriter()\ndef builder = new groovy.xml.MarkupBuilder(writer)\n\ndef web = builder.'web-app' {\n    builder.'display-name'('Groovy WebApp')\n}    \n\ndef result = writer.toString().replaceAll(\"\\r\",\"\")\n \nassert \"\\n\"+result == \"\"\"\n<web-app>\n  <display-name>Groovy WebApp</display-name>\n</web-app>\"\"\"   "
  },
  {
    "path": "listings/chap11/snippet1106_AntBuilderIf.groovy",
    "content": "ant = new AntBuilder()\nif ( ! System.properties.'java.version'.contains('1.7')) {\n    ant.fail 'This build script requires JDK 1.7.x but was ' +\n        System.properties.'java.version'\n} \n// further action"
  },
  {
    "path": "listings/chap11/snippet1106_AntIf.xml",
    "content": "<project name=\"AntIf\" default=\"main\" >\n\n    <target name=\"check.java.version\">\n        <condition property=\"java.version.ok\">\n            <contains string=\"${java.version}\" substring=\"1.4\"/>\n        </condition>        \n        <fail unless=\"java.version.ok\">\n            This build script requires JDK 1.4.x. \n        </fail>\n    </target>\n\n    <target name=\"main\" \n        depends=\"check.java.version\" \n        if=\"java.version.ok\">\n    \n        <!-- further action -->\n    \n    </target>\n\n</project>\n"
  },
  {
    "path": "listings/chap11/snippet1107_Printer.groovy",
    "content": "import groovy.swing.SwingBuilder\n\nswing = new SwingBuilder()\nbutton = swing.button('Print')\n\nframe = swing.frame(title:'Printer') {\n  panel {\n    textField(columns:10)\n    widget(button)\n  }\n}\n\nbutton.actionPerformed = {\n  println frame.title\n}\n\nframe.pack()\nframe.visible = true\n"
  },
  {
    "path": "listings/chap11/snippet1107_binding.txt",
    "content": "import java.beans.*\n\nclass Person {\n\n  private String name\n  private int age\n  final private PropertyChangeSupport this$propChangeSupport =\n      new PropertyChangeSupport(this)\n  final private VetoableChangeSupport this$vetoChangeSupport =\n      new VetoableChangeSupport(this)\n\n  void addPropertyChangeListener(PropertyChangeListener listener) {\n    this$propChangeSupport.addPropertyChangeListener(listener)\n  }\n\n  void addPropertyChangeListener(String name,\n                                 PropertyChangeListener listener) {\n    this$propChangeSupport.addPropertyChangeListener(name, listener)\n  }\n\n  void removePropertyChangeListener(PropertyChangeListener listener) {\n    this$propChangeSupport.removePropertyChangeListener(listener)\n  }\n\n  void removePropertyChangeListener(String name,\n                                    PropertyChangeListener listener) {\n    this$propChangeSupport.removePropertyChangeListener(name, listener)\n  }\n\n  void firePropertyChange(String name, oldValue, newValue) {\n    this$propChangeSupport.firePropertyChange(name, oldValue, newValue)\n  }\n\n  PropertyChangeListener[] getPropertyChangeListeners() {\n    return this$propChangeSupport.getPropertyChangeListeners()\n  }\n\n  PropertyChangeListener[] getPropertyChangeListeners(String name) {\n    return this$propChangeSupport.getPropertyChangeListeners(name)\n  }\n\n  void setName(String value) {\n    this.firePropertyChange('name', name, name = value )\n  }\n\n  void addVetoableChangeListener(VetoableChangeListener listener) {\n    this$vetoChangeSupport.addVetoableChangeListener(listener)\n  }\n\n  void addVetoableChangeListener(String name,\n                                 VetoableChangeListener listener) {\n    this$vetoChangeSupport.addVetoableChangeListener(name, listener)\n  }\n\n  void removeVetoableChangeListener(VetoableChangeListener listener) {\n    this$vetoChangeSupport.removeVetoableChangeListener(listener)\n  }\n\n  void removeVetoableChangeListener(String name,\n                                    VetoableChangeListener listener) {\n    this$vetoChangeSupport.removeVetoableChangeListener(name, listener)\n  }\n\n  void fireVetoableChange(String name, oldValue, newValue) {\n    this$vetoChangeSupport.fireVetoableChange(name, oldValue, newValue)\n  }\n\n  VetoableChangeListener[] getVetoableChangeListeners() {\n    return this$vetoChangeSupport.getVetoableChangeListeners()\n  }\n\n  VetoableChangeListener[] getVetoableChangeListeners(String name) {\n    return this$vetoChangeSupport.getVetoableChangeListeners(name)\n  }\n\n  void setAge(int value) throws PropertyVetoException {\n    this.fireVetoableChange('age', age, value)\n    age = value\n  }\n\n  String getName() {\n    name\n  }\n\n  int getAge() {\n    age\n  }\n\n}\n"
  },
  {
    "path": "listings/chap12/Listing_12_01_info_jdk6_only.groovy",
    "content": "def newline = \"\\n\"\n\nassert newline.toString() == \"\\n\"\n\nassert newline.dump() ==\n'''<java.lang.String@a value=\n offset=0 count=1 hash=10>'''\n"
  },
  {
    "path": "listings/chap12/Listing_12_01_info_jdk7_only.groovy",
    "content": "def newline = \"\\n\"\n\nassert newline.toString() == \"\\n\"\n\nassert newline.dump() ==\n    '''<java.lang.String@a value=\n hash=10 hash32=0>'''\n\nassert newline.inspect() == /'\\n'/\n"
  },
  {
    "path": "listings/chap12/Listing_12_01_info_jdk8_plus.groovy",
    "content": "def newline = \"\\n\"\n\nassert newline.toString() == \"\\n\"\n\nassert newline.dump() ==\n    '''<java.lang.String@a value=\n hash=10>'''\n\nassert newline.inspect() == /'\\n'/\n"
  },
  {
    "path": "listings/chap12/Listing_12_02_properties.groovy",
    "content": "class MyClass {\n    def first = 1                   // read-write property\n    def getSecond() { first * 2 }   // read-only property\n    public third = 3                // public field\n    def myMethod() { }              // public method\n}\n\ndef obj = new MyClass()\n\nassert obj.hasProperty('first')                 //|#1\nassert obj.respondsTo('myMethod')               //|#2\n\ndef keys = ['first', 'second', 'class']\nassert obj.properties.keySet() == new HashSet(keys)\n\nassert 1 == obj.properties['first']             //|#3\nassert 1 == obj.properties.first                //|#3\n\nassert 1 == obj.first                           //|#4\nassert 1 == obj['first']    // getAt('first')   //|#4\n\ndef one = 'first'\ndef two = 'second'\nobj[one] = obj[two]         // putAt(one)       //#5\nassert obj.dump() =~ 'first=2'                  //#6\n//#1 Property check\n//#2 Method check\n//#3 Properties map\n//#4 Direct access\n//#5 Dynamic assignment\n//#6 Field introspection\n"
  },
  {
    "path": "listings/chap12/Listing_12_03_File_Iteration.groovy",
    "content": "file = new File('Listing_12_03_File_Iteration.groovy')\nfile.each { println it }\nassert file.any { it =~ /File/ }\nassert 3 == file.findAll { it =~ /File/ }.size()\n\nassert 5 == file.grep { it }.size()\n"
  },
  {
    "path": "listings/chap12/Listing_12_04_Filesystem.groovy",
    "content": "import static groovy.io.FileType.DIRECTORIES\nimport static groovy.io.FileType.FILES\n\ndef topDir = new File('../chap09')\ndef srcDir = new File(topDir, 'src')\n\ndirs = []\nsrcDir.eachDir { dirs << it.name }                                  //#A\nassert  ['main', 'test'] == dirs\n\ndirs = []\ntopDir.eachDirRecurse { dirs << it.name }                           //#B\nassert dirs.containsAll(['gradle', 'src', 'main'])\nassert dirs.containsAll(['groovy', 'services', 'wrapper'])\n\ndirs = []\ntopDir.eachDirMatch(~/[^l]*/) { dirs << it.name }                   //#C\nassert dirs == ['src']\n\nfiles = []\ntopDir.eachFile { files << it.name }                                //#D\nassert files.contains('Listing_09_01_ToStringDetective.groovy')\nassert files.contains('src')\n\nfiles = []\ntopDir.eachFile(FILES) { files << it.name }                         //#E\nassert files.contains('Listing_09_01_ToStringDetective.groovy')\n\ncount = 0\nsrcDir.eachFileRecurse { if (it.directory) count++ }                //#F\nassert 9 == count\n\ncount = 0\nsrcDir.eachFileRecurse(DIRECTORIES) { count++ }                     //#G\nassert 9 == count\n\nfiles = []\ntopDir.eachFileMatch(~/Listing_09_01.*/) { files << it.name }       //#H\nassert ['Listing_09_01_ToStringDetective.groovy'] == files\n//#A Closure recording directory names\n//#B Recursively record directory names\n//#C Record directory names matching a pattern (.gradle is excluded here)\n//#D Record filenames and directory names\n//#E Record filenames\n//#F Count directory names recursively\n//#G Count directory names recursively, alternative solution\n//#H Record filenames and directory names matching a pattern\n"
  },
  {
    "path": "listings/chap12/Listing_12_05_Traversal.groovy",
    "content": "import static groovy.io.FileType.ANY\nimport static groovy.io.FileVisitResult.SKIP_SUBTREE\n\ndef totalSize = 0\ndef count = 0\ndef sortByTypeThenName = { a, b ->\n  a.isFile() != b.isFile() ?\n      a.isFile() <=> b.isFile() :\n      a.name <=> b.name\n}\ndef log = []\n\ninputDir = new File('../chap09/')\n\ninputDir.traverse(\n    type         : ANY,\n    nameFilter   : ~/.*groovy.*/,\n    excludeNameFilter : ~/.*Test.*/,\n    preDir       : {\n      if (it.name =~ '.?gradle|build') return SKIP_SUBTREE\n      count = 0\n      totalSize = 0\n    },\n    postDir      : {\n      if (count) {\n        log << \"Found $count files in $it.name : $totalSize bytes\"\n        count = 0\n        totalSize = 0\n      }\n    },\n    postRoot     : true,\n    sort         : sortByTypeThenName\n) {it -> totalSize += it.size(); count++ }\nprintln log.join('\\n')\nassert log.size() == 3\nassert log*.replaceAll(/\\d+/, '*').join('\\n') == '''\nFound * files in regina : * bytes\nFound * files in services : * bytes\nFound * files in chap* : * bytes\n'''.trim()\n"
  },
  {
    "path": "listings/chap12/Listing_12_06_File_Read.groovy",
    "content": "example = new File('data/example.txt')\n\nlines = ['line one', 'line two', 'line three']\nassert lines == example.readLines()\n\nexample.eachLine {\n  assert it.startsWith('line')\n}\n\nhex = []\nexample.eachByte { hex << it }\nassert hex.size() == example.length()\n\nexample.splitEachLine(/\\s/) {\n  assert 'line' == it[0]\n}\n\nexample.withReader { reader ->\n  assert 'line one' == reader.readLine()\n}\n"
  },
  {
    "path": "listings/chap12/Listing_12_07_File_Write.groovy",
    "content": "def outFile = new File('data/example.txt')\n\ndef lines = ['line one','line two','line three']\n\noutFile.write(lines[0..1].join(\"\\n\"))                     //#A\noutFile.append(\"\\n\"+lines[2])                             //#A\n\nassert lines == outFile.readLines()\n\noutFile.withWriter { writer ->                            //#B\n  writer.writeLine(lines[0])                              //#B\n}                                                         //#B\noutFile.withWriterAppend('ISO8859-1') { writer ->         //#B\n  writer << lines[1] << \"\\n\"                              //#B\n}\noutFile << lines[2]                                       //#C\n//#A Writing/appending with simple method calls\n//#B Writing/appending with closures\n//#C Appending with the leftshift operator\n"
  },
  {
    "path": "listings/chap12/Listing_12_08_Writer_LeftShift.groovy",
    "content": "TimeZone.default = TimeZone.getTimeZone(\"CET\")\nreader = new StringReader('abc')\nwriter = new StringWriter()\n\nwriter << \"\\nsome String\"   << \"\\n\"\nwriter << [a:1, b:2]        << \"\\n\"\nwriter << [3,4]             << \"\\n\"\nwriter << new Date(0)       << \"\\n\"\nwriter << reader            << \"\\n\"\n\nassert writer.toString() == '''\nsome String\n[a:1, b:2]\n[3, 4]\nThu Jan 01 01:00:00 CET 1970\nabc\n'''\n"
  },
  {
    "path": "listings/chap12/Listing_12_09_File_Transform_jdk7_plus.groovy",
    "content": "def n = System.lineSeparator()                    //#1\n\nreader = new StringReader('abc')\nwriter = new StringWriter()\n\nreader.transformChar(writer) { it.next() }        //#A\nassert 'bcd' == writer.toString()\n\nreader = new File('data/example.txt').newReader()\nwriter = new StringWriter()\n\nreader.transformLine(writer) { it - 'line' }      //#B\nassert \" one${n} two${n} three${n}\" == writer.toString()\n\ninput  = new File('data/example.txt')\nwriter = new StringWriter()\n\ninput.filterLine(writer) { it =~ /one/ }          //#C\nassert \"line one${n}\" == writer.toString()\n\nwriter = new StringWriter()\nwriter << input.filterLine { it.size() > 8 }      //#2\nassert \"line three${n}\"  == writer.toString()\n//#1 System dependent line separator\n//#2 Read only long lines\n//#A Transform ‘abc’ to ‘bcd’\n//#B Chop ‘line’ from each line of the example file\n//#C Read only lines containing “one”\n"
  },
  {
    "path": "listings/chap12/Listing_12_10_File_ObjectStreams.groovy",
    "content": "file = new File('objects.dat')\nfile.deleteOnExit()                                //#A\n\nobjects = [1, \"Hello Groovy!\", new Date()]\nfile.withObjectOutputStream { outstream ->\n  objects.each {\n    outstream << it                                //#B\n  }\n}\n\nretrieved = []\nfile.withObjectInputStream { instream ->\n  instream.eachObject {\n    retrieved << it                                //#C\n  }\n}\n\nassert retrieved == objects\n//#A Clean up after ourselves\n//#B Serialize each object in the list in turn\n//#C Deserialize each object in turn\n"
  },
  {
    "path": "listings/chap12/Listing_12_11_Temp_Dir.groovy",
    "content": "File tempDir = File.createTempDir()                          //#A\n\nassert tempDir.directorySize() == 0                          //#B\n\nFile source = new File(tempDir, 'input.dat')                 //#C\nsource.bytes = \"hello world\".bytes\n\nassert tempDir.directorySize() == 11                         //#D\n\nFile destination = new File(tempDir, 'output.dat')\n\ndestination.withDataOutputStream { os->                      //#E\n    source.withDataInputStream { is->\n        os << is\n    }\n}\n\nassert tempDir.directorySize() == 22\n\ntempDir.deleteDir()                                         //#F\n//#A Create a temporary directory\n//#B Check that the directory is empty\n//#C Create a file and set the file contents\n//#D Check that the directory size increased\n//#E Copy the file and check that the directory size doubled\n//#F Delete the directory\n"
  },
  {
    "path": "listings/chap12/Listing_12_12_Threads.groovy",
    "content": "import java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.LinkedBlockingQueue;\n\nThread.metaClass.'static'.getName = { Thread.currentThread().name } //#A\n\nBlockingQueue sharedQueue = [] as LinkedBlockingQueue               //#B\n\nThread.start('push') {                                              //#C\n    10.times {\n        try {\n            println(\"${Thread.name}\\t: ${it}\")\n            sharedQueue << it\n            sleep 100\n        } catch (InterruptedException ignore) {}\n    }\n}\n\nThread.start('pop') {                                               //#D\n    for (i in 0..9) {\n        sleep 200\n        println(\"${Thread.name}\\t: ${sharedQueue.take()}\")\n\n    }\n}\n//#A Create a new method to get the thread name\n//#B Create a shared queue\n//#C Start a thread producing 10 items\n//#D Start a thread consuming 10 items\n"
  },
  {
    "path": "listings/chap12/Listing_12_13_Processes_UnixCommands.groovy",
    "content": "// works for unix-based systems\ndef listFiles = 'ls'.execute()\ndef ignoreCase = \"tr '[A-Z]' '[a-z]'\".execute()\ndef reverseSort = 'sort -r'.execute()\n\nlistFiles | ignoreCase | reverseSort\n\nreverseSort.waitForOrKill(1000)\nif (reverseSort.exitValue()) {\n    print reverseSort.err.text\n} else {\n    print reverseSort.text\n}\n\n"
  },
  {
    "path": "listings/chap12/Listing_12_14_Processes_ZipUnzip.groovy",
    "content": "// works for systems with gzip and gunzip on the path\ndef outputBuffer = new StringBuffer()\ndef errorBuffer  = new StringBuffer()\n\nzipProcess   = 'gzip -c'.execute()\nunzipProcess = 'gunzip -c'.execute()\n\nunzipProcess.consumeProcessOutput(outputBuffer, errorBuffer)\nzipProcess.consumeProcessErrorStream(errorBuffer)\n\nzipProcess | unzipProcess\nzipProcess.withWriter { writer ->\n  writer << 'Hello World'\n}\nunzipProcess.waitForOrKill(1000)\n\nprintln 'Output: ' + outputBuffer\nprintln 'Error : ' + errorBuffer\n"
  },
  {
    "path": "listings/chap12/Listing_12_15_SimpleTemplateEngine.groovy",
    "content": "mailReminder =                                               //#A\n'''\nDear ${salutation?salutation+' ':''}$lastname,\nanother month has passed and it's time for these\n<%=tasks.size()%> tasks:\n<% tasks.each { %>- $it \n<% } %> \nyour collaboration is very much appreciated\n'''\n\ndef engine   = new groovy.text.SimpleTemplateEngine()       \ndef template = engine.createTemplate(mailReminder)          \ndef binding  = [                                            \n    salutation: 'Mrs.',                                      //|#B\n    lastname  : 'Davis',                                     //|#B\n    tasks     : ['visit the Groovy in Action (GinA) page',   //|#B\n                 'chat with GinA readers']                   //|#B\n]\n\nassert template.make(binding).toString() ==                   //#C\n'''\nDear Mrs. Davis,\nanother month has passed and it's time for these\n2 tasks:\n- visit the Groovy in Action (GinA) page \n- chat with GinA readers \n \nyour collaboration is very much appreciated\n'''\n//#A Text of template containing placeholders\n//#B Variables to substitute in the template\n//#C Evaluate the template against the binding\n"
  },
  {
    "path": "listings/chap12/Listing_12_16_GroovletExample.groovy",
    "content": "@Grab('org.eclipse.jetty.aggregate:jetty-server:8.1.16.v20140903')\n@Grab('org.eclipse.jetty.aggregate:jetty-servlet:8.1.16.v20140903')\n@Grab('javax.servlet:javax.servlet-api:3.0.1')\n\nimport org.eclipse.jetty.server.Server\nimport org.eclipse.jetty.servlet.*\nimport groovy.servlet.*\nimport static org.eclipse.jetty.servlet.ServletContextHandler.*\n\ndef server = new Server(1234)\ndef context = new ServletContextHandler(server, \"/\", SESSIONS)\ncontext.resourceBase = \".\"\ncontext.addServlet(GroovyServlet, \"*.groovy\")\nserver.start()\n"
  },
  {
    "path": "listings/chap12/Listing_12_17_HelloWorldGroovlet.groovy",
    "content": "html.html{\n  head {\n    title 'Groovlet Demonstrator'\n  }\n  body { h1 'Welcome to the World of Groovlets' }\n}\n"
  },
  {
    "path": "listings/chap12/Listing_12_19_InspectGroovlet.groovy",
    "content": "html.html{\n  head {\n    title 'Groovlet Demonstrator'\n  }\n  body {\n    h1 'Variables in the Binding:'\n    table(summary:'binding') {\n      tbody {\n        binding.variables.each { key, value ->\n          tr {\n            td key.toString()\n            td(value ? value.toString() : 'null')\n} } } } } }\n"
  },
  {
    "path": "listings/chap12/Listing_12_20_HiLowGame.groovy",
    "content": "def session = request.session\ndef guess   = params.guess\nguess = guess ? guess.toInteger() : null\nif (params.restart) guess = null\n\nif (!session.goal || params.restart) {               //#A\n    session.goal = (Math.random()*100).toInteger()   //#A\n}                                                    //#A\ndef goal = session.goal\n\nhtml.html{ head { title 'Think of a Number'  }             //#B\n    body {\n        h1 'Think of a Number'\n        if (goal && guess) {\n            div \"Your guess $guess is \"                    //#C\n            switch (guess) {\n                case goal        : div 'correct!'; break   //#D\n                case {it < goal} : div 'too low' ; break   //#D\n                case {it > goal} : div 'too high'; break   //#D\n            }\n        }\n        p \"What's your guess (0..100)?\"\n        form(action:'Listing_12_20_HiLowGame.groovy'){          //#E\n            input(type:'text', name:'guess', '')\n            button(type:'submit', 'Guess')\n            button(type:'submit', name:'restart', value:'true',\n                'New Game')\n}   }   }\n//#A Generate a number to guess, if necessary\n//#B Start a builder to generate the HTML\n//#C Use a GString as a simple template for text\n//#D Classify the guess appropriately\n//#E Display a form posting to the same page again\n"
  },
  {
    "path": "listings/chap12/Listing_12_21_NumberTemplate.txt",
    "content": "see: Number.template.html"
  },
  {
    "path": "listings/chap12/Listing_12_22_TemplateGroovlet.groovy",
    "content": "def session = request.session\ndef guess   = params.guess\nguess = guess ? guess.toInteger() : null\nif (params.restart) guess = null\n\nif (!session.goal || params.restart) {\n  session.goal = (Math.random()*100).toInteger()\n}\n\ndef engine   = new groovy.text.SimpleTemplateEngine()      //#1\ndef source   = getClass().classLoader.                     //#1\n    getResource('Number.template.html')                    //#1\ndef template = engine.createTemplate(source)               //#1\nout << template.make(guess: guess, goal: session.goal)     //#1\n//#1 Template rendering code\n"
  },
  {
    "path": "listings/chap12/Number.template.html",
    "content": "<html>\n  <head>\n    <title>Think of a Number</title>\n  </head>\n  <body>\n    <h1>Think of a Number</h1>\n    <% if (guess) { %>\n    Your guess $guess is <%\n    switch (guess) {\n      case goal : out << 'correct!'; break\n      case {it < goal} : out << 'too low' ; break\n      case {it > goal} : out << 'too high'; break\n    }\n    } %>\n    <p>What&quot;s your guess (0..100)?</p>\n\n    <form action='Listing_12_22_TemplateGroovlet.groovy'>\n      <input type='text' name='guess'>\n      <button type='submit'>Guess</button>\n      <button type='submit' name='restart' value='true'>New Game\n      </button>\n    </form>\n  </body>\n</html>\n"
  },
  {
    "path": "listings/chap12/data/example.txt",
    "content": "line one\nline two\nline three"
  },
  {
    "path": "listings/chap12/snippet1201_SlowTyping.groovy",
    "content": "text = \"\"\"\nThis text appears\nslowly on the screen\nas if someone was\ntyping it.\n\"\"\"\nfor (c in text) {\n  sleep 100\n  print c\n}\n"
  },
  {
    "path": "listings/chap12/snippet1201_UseCategory.groovy",
    "content": "class StringCasingCategory {\n  static String lower(String string) {\n    return string.toLowerCase()\n  }\n}\n\nuse(StringCasingCategory) {\n  assert \"groovy\" == \"GroOvy\".lower()\n}\n"
  },
  {
    "path": "listings/chap12/snippet1202_base64.groovy",
    "content": "byte[] data = new byte[256]\nfor (i in 0..255) { data[i] = i }\n\nstore = data.encodeBase64().toString()\n\nassert store.startsWith('AAECAwQFBg')\nassert store.endsWith  ('r7/P3+/w==')\n\nrestored = store.decodeBase64()\n\nassert data.toList() == restored.toList()"
  },
  {
    "path": "listings/chap12/web.xml",
    "content": "<web-app xmlns=\"http://java.sun.com/xml/ns/javaee\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd\" version=\"3.0\">\n    <servlet>\n        <servlet-name>Groovlet</servlet-name>\n        <servlet-class>groovy.servlet.GroovyServlet</servlet-class>\n    </servlet>\n    <servlet>\n        <servlet-name>Template</servlet-name>\n        <servlet-class>groovy.servlet.TemplateServlet</servlet-class>\n    </servlet>\n\n    <servlet-mapping>\n        <servlet-name>Groovlet</servlet-name>\n        <url-pattern>*.groovy</url-pattern>\n    </servlet-mapping>\n    <servlet-mapping>\n        <servlet-name>Template</servlet-name>\n        <url-pattern>*.html</url-pattern>\n    </servlet-mapping>\n    <servlet-mapping>\n        <servlet-name>Template</servlet-name>\n        <url-pattern>*.gsp</url-pattern>\n    </servlet-mapping>\n\n</web-app>\n"
  },
  {
    "path": "listings/chap13/Listing_13_01_Connecting.groovy",
    "content": "@Grab('org.hsqldb:hsqldb:2.3.2')\n@GrabConfig(systemClassLoader=true)\n//////////////////////////////////\n\n\nimport groovy.sql.Sql\n\ndef url = 'jdbc:hsqldb:mem:GinA'\ndef user = 'sa'\ndef password = ''\ndef driver = 'org.hsqldb.jdbcDriver'\ndef sql = Sql.newInstance(url, user, password, driver)\n\n// use 'sql' instance ...\n// optional test of a system table within HSQLDB\nassert sql.firstRow('SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS')[0] == 1\n\nsql.close()\n"
  },
  {
    "path": "listings/chap13/Listing_13_02_ConnectingDataSource.groovy",
    "content": "@Grab('org.hsqldb:hsqldb:2.3.2')\n@GrabConfig(systemClassLoader=true)\n//////////////////////////////////\n\n\n\nimport groovy.sql.Sql\nimport org.hsqldb.jdbc.JDBCDataSource\n\ndef dataSource = new JDBCDataSource(\n    database: 'jdbc:hsqldb:mem:marathon', user: 'sa', password: '')\ndef sql = new Sql(dataSource)\n\n// use 'sql' instance ...\n// optional test of a system table within HSQLDB\nassert sql.firstRow('SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS')[0] == 1\n\nsql.close()\n"
  },
  {
    "path": "listings/chap13/Listing_13_03_Creating.groovy",
    "content": "@Grab('org.hsqldb:hsqldb:2.3.2')\n@GrabConfig(systemClassLoader=true)\n//////////////////////////////////\n\n\n\n\nimport groovy.sql.Sql\n\ndef url = 'jdbc:hsqldb:mem:GinA'\ndef user = 'sa'\ndef password = ''\ndef driver = 'org.hsqldb.jdbcDriver'\ndef sql = Sql.newInstance(url, user, password, driver)\n\nsql.execute '''\n  CREATE TABLE Athlete (\n    athleteId   INTEGER GENERATED BY DEFAULT AS IDENTITY,    --#A\n    firstname   VARCHAR(64),\n    lastname    VARCHAR(64),\n    dateOfBirth DATE\n  );\n'''\n\nsql.close()\n//#A Column value will be automatically generated"
  },
  {
    "path": "listings/chap13/Listing_13_04_DbUtilClass.txt",
    "content": "see: util/DbUtil.groovy"
  },
  {
    "path": "listings/chap13/Listing_13_05_Inserting.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\n\nsql.execute '''\n  INSERT INTO Athlete (firstname, lastname, dateOfBirth)\n  VALUES ('Paul', 'Tergat', '1969-06-17')\n'''                                                                   //#A\n\ndef data = [first: 'Khalid', last: 'Khannouchi', birth: '1971-12-22']\ndef keys = sql.executeInsert \"\"\"\n  INSERT INTO Athlete (firstname, lastname, dateOfBirth)\n  VALUES (${data.first}, ${data.last}, ${data.birth})\n\"\"\"                                                                   //#B\nassert keys[0] == [1]                                                 //#1\n\ndef insertSql = '''\n  INSERT INTO Athlete (firstname, lastname, dateOfBirth)\n  VALUES (?,?,?)\n'''\ndef params = ['Ronaldo', 'da Costa', '1970-06-07']\ndef keyColumnNames = ['ATHLETEID']\nkeys = sql.executeInsert insertSql, params, keyColumnNames            //#C\nassert keys[0] == [ATHLETEID: 2]                                      //#2\n\nsql.close()\n//#A Insert using plain statement\n//#B GString variant\n//#C List of params variant\n//#1 Checking generated keys for second row\n//#2 Checking generated athleteId key for third row\n"
  },
  {
    "path": "listings/chap13/Listing_13_06_Reading.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\n\ndef expected = ['Paul Tergat', 'Khalid Khannouchi', 'Ronaldo da Costa']\n\ndef rowNum = 0\nsql.query('SELECT firstname, lastname FROM Athlete') { resultSet ->   //#1\n  while (resultSet.next()) {                                          //#2\n    def first = resultSet.getString(1)                                //#3\n    def last = resultSet.getString('lastname')                        //#3\n    assert expected[rowNum++] == \"$first $last\"\n  }\n}\n\nrowNum = 0\nsql.eachRow('SELECT firstname, lastname FROM Athlete') { row ->       //#4\n  def first = row[0]                                                  //#5\n  def last = row.lastname                                             //#5\n  assert expected[rowNum++] == \"$first $last\"\n}\n\ndef first = sql.firstRow('SELECT lastname, dateOfBirth FROM Athlete') //#6\nassert first.values().sort().join(',') == 'Tergat,1969-06-17'         //#5\n\nList athletes = sql.rows('SELECT firstname, lastname FROM Athlete')   //#7\nassert athletes.size() == 3\nassert athletes.collect { \"$it.FIRSTNAME ${it[-1]}\" } == expected     //#5\n\nassert sql.firstRow('SELECT COUNT(*) AS num FROM Athlete').num == 3   //#8\n//#1 Read using query\n//#2 External iteration on the ResultSet\n//#3 Access properties via JDBC API calls\n//#4 Read using rows\n//#5 Access properties via map or list styles\n//#6 Read using firstRow\n//#7 Read using rows\n//#8 More efficient size calculation\n"
  },
  {
    "path": "listings/chap13/Listing_13_07_Updating.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\n\nsql.execute '''\n  INSERT INTO Athlete (lastname) VALUES ('da Costa')\n'''\n\nsql.execute '''\n  UPDATE Athlete SET firstname='Ronaldo' where lastname='da Costa'\n'''\n\ndef updateCount = sql.executeUpdate '''\n  UPDATE Athlete SET dateOfBirth='1970-06-07' where lastname='da Costa'\n'''\nassert updateCount == 1                                               //#A\n\ndef row = sql.firstRow '''\n  SELECT * FROM Athlete where lastname = 'da Costa'\n'''\nassert \"${row.firstname} ${row.lastname} ${row.dateofbirth}\" ==\n    'Ronaldo da Costa 1970-06-07'\n\nsql.close()\n//#A Check one row was updated\n"
  },
  {
    "path": "listings/chap13/Listing_13_08_Delete.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)                                                  //#A\n\nassert sql.firstRow('SELECT COUNT(*) as num FROM Athlete').num == 3   //#B\n\nsql.execute \"DELETE FROM Athlete WHERE lastname = 'Tergat'\"\n\nassert sql.firstRow('SELECT COUNT(*) as num FROM Athlete').num == 2   //#C\n//#A Populate using our helper method\n//#B Check initially three rows\n//#C Two rows left after delete\n"
  },
  {
    "path": "listings/chap13/Listing_13_09_Transactions.groovy",
    "content": "import static util.DbUtil.*\n\ndef sql = create()\npopulate(sql)\n\nsql.withTransaction {\n    insertAthlete(sql, 'Haile', 'Gebrselassie', '1973-04-18')\n    insertAthlete(sql, 'Patrick', 'Makau', '1985-03-02')\n}\n\nassert sql.firstRow('SELECT COUNT(*) as num FROM Athlete').num == 5\n\n// modify above to show transaction rollback\n/*\ntry {\n  sql.withTransaction {\n    insertAthlete(sql, 'Haile', 'Gebrselassie', '1973-04-18')\n    insertAthlete(sql, 'Patrick', 'Makau' * 100, '1985-03-02')\n  }\n} catch(ignore) { println ignore.message }\nassert sql.firstRow('SELECT COUNT(*) as num FROM Athlete').num == 3\n\n */"
  },
  {
    "path": "listings/chap13/Listing_13_10_Batching.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\nDbUtil.enableLogging()\n\nsql.withBatch { stmt ->\n    stmt.addBatch '''\n    INSERT INTO Athlete (firstname, lastname, dateOfBirth)\n    VALUES ('Paula', 'Radcliffe', '1973-12-17')'''\n    stmt.addBatch \"\"\"\n    INSERT INTO Record (time, venue, whenRun, fkAthlete)\n      SELECT ${2*60*60+15*60+25}, 'London', '2003-04-13',\n      athleteId FROM Athlete WHERE lastname='Radcliffe'\"\"\"\n}\n//22/04/2013 6:34:59 AM groovy.sql.BatchingStatementWrapper processResult\n//FINE: Successfully executed batch with 2 command(s)\n\nassert sql.firstRow('SELECT COUNT(*) as num FROM Athlete').num == 4\nassert sql.firstRow('SELECT COUNT(*) as num FROM Record').num == 5\n\ndef qry = '''\n  INSERT INTO Athlete (firstname, lastname, dateOfBirth)\n  VALUES (?,?,?)\n'''\nsql.withBatch(3, qry) { ps ->\n    ps.addBatch('Catherine', 'Ndereba', '1972-07-21')\n    ps.addBatch('Naoko', 'Takahashi', '1972-05-06')\n    ps.addBatch('Tegla', 'Loroupe', '1973-05-09')\n    ps.addBatch('Ingrid', 'Kristiansen', '1956-03-21')\n}\n//Sep 24, 2014 10:32:03 PM groovy.sql.BatchingStatementWrapper processResult\n//FINE: Successfully executed batch with 3 command(s)\n//Sep 24, 2014 10:32:03 PM groovy.sql.BatchingStatementWrapper processResult\n//FINE: Successfully executed batch with 1 command(s)\n\nassert sql.firstRow('SELECT COUNT(*) as num FROM Athlete').num == 8\n"
  },
  {
    "path": "listings/chap13/Listing_13_11_Paging.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\n\ndef qry = 'SELECT * FROM Athlete'\nassert sql.rows(qry, 1, 2)*.lastname == ['Tergat', 'Khannouchi']\nassert sql.rows(qry, 3, 2)*.lastname == ['da Costa']\n"
  },
  {
    "path": "listings/chap13/Listing_13_12_Metadata.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\n\ndef dump(sql, tablename) {\n  println \" CONTENT OF TABLE ${tablename} \".center(32, '-')\n  sql.eachRow('SELECT * FROM ' + tablename) { rs ->\n    def meta = rs.getMetaData()\n    if (meta.columnCount <= 0) return\n    for (i in 0..<meta.columnCount) {\n      print \"${i}: ${meta.getColumnLabel(i + 1)}\".padRight(20)        //#1\n      println rs[i]?.toString()                                       //#2\n    }\n    println '-' * 32\n  }\n}\n\ndef oldOut = System.out\ndef baos = new ByteArrayOutputStream()\nSystem.setOut(new PrintStream(baos))                                  //#3\n\ndump(sql, 'Athlete')\nSystem.setOut(oldOut)\nassert baos.toString().readLines()*.trim().join('\\n') == '''\\\n--- CONTENT OF TABLE Athlete ---\n0: ATHLETEID        0\n1: FIRSTNAME        Paul\n2: LASTNAME         Tergat\n3: DATEOFBIRTH      1969-06-17\n--------------------------------\n0: ATHLETEID        1\n1: FIRSTNAME        Khalid\n2: LASTNAME         Khannouchi\n3: DATEOFBIRTH      1971-12-22\n--------------------------------\n0: ATHLETEID        2\n1: FIRSTNAME        Ronaldo\n2: LASTNAME         da Costa\n3: DATEOFBIRTH      1970-06-07\n--------------------------------\\\n'''\n//#1 Counts from 1\n//#2 Counts from 0 and possibly null\n//#3 Capture standard out\n"
  },
  {
    "path": "listings/chap13/Listing_13_13_MoreMetadata.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\n\ndef dump2(sql, tablename) {\n  def printColNames = { meta ->\n    def width = meta.columnCount * 12\n    println \" CONTENT OF TABLE ${tablename} \".center(width, '-')\n    (1..meta.columnCount).each {\n      print meta.getColumnLabel(it).padRight(12)\n    }\n    println()\n    println '-' * width\n  }\n  def printRow = { row ->\n    row.toRowResult().values().each {\n      print it.toString().padRight(12)\n    }\n    println()\n  }\n  sql.eachRow('SELECT * FROM ' + tablename, printColNames, printRow)\n}\n\ndef oldOut = System.out\ndef baos = new ByteArrayOutputStream()\nSystem.setOut(new PrintStream(baos))\n\ndump2(sql, 'Athlete')\nassert baos.toString().readLines()*.trim().join('\\n') == '''\\\n----------- CONTENT OF TABLE Athlete -----------\nATHLETEID   FIRSTNAME   LASTNAME    DATEOFBIRTH\n------------------------------------------------\n0           Paul        Tergat      1969-06-17\n1           Khalid      Khannouchi  1971-12-22\n2           Ronaldo     da Costa    1970-06-07\\\n'''\n\nbaos.reset()\ndump2(sql, 'Record')\nSystem.setOut(oldOut)\nassert baos.toString().readLines()*.trim().join('\\n') == '''\\\n----------------- CONTENT OF TABLE Record ------------------\nRECORDID    TIME        VENUE       WHENRUN     FKATHLETE\n------------------------------------------------------------\n0           7495        Berlin      2003-09-28  0\n1           7538        London      2002-04-14  1\n2           7542        Chicago     1999-10-24  1\n3           7565        Berlin      1998-09-20  2\\\n'''\n"
  },
  {
    "path": "listings/chap13/Listing_13_14_NamedOrdinal.groovy",
    "content": "import groovy.transform.Canonical\nimport util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\n\ndef insertPrefix = '''\nINSERT INTO Athlete (firstname, lastname, dateOfBirth) VALUES\n'''\n\nsql.execute insertPrefix + '(:first,:last,:dob)', first: 'Ingrid',\n        last: 'Kristiansen', dob: '1956-03-21'\n\ndef loroupe = [first: 'Tegla', last: 'Loroupe', dob: '1973-05-09']\nsql.execute insertPrefix + '(:first,:last,:dob)', loroupe\n\n@Canonical class Athlete { String first, last, dob }\n\ndef ndereba = new Athlete('Catherine', 'Ndereba', '1972-07-21')\nsql.execute insertPrefix + '(?.first,?.last,?.dob)', ndereba\n\ndef takahashi = new Athlete('Naoko', 'Takahashi')\ndef takahashiExtra = [dob: '1972-05-06']\ndef namedOrdinalSuffix = '(?1.first,?1.last,?2.dob)'\nsql.execute insertPrefix + namedOrdinalSuffix, takahashi, takahashiExtra\n\nassert sql.firstRow('SELECT COUNT(*) as num FROM Athlete').num == 7\n"
  },
  {
    "path": "listings/chap13/Listing_13_15_StoredProcBasic.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\n\nsql.execute '''\n  CREATE FUNCTION SELECT_ATHLETE_RECORD ()\n  RETURNS TABLE (lastname VARCHAR(64), venue VARCHAR(64), whenRun DATE)\n  READS SQL DATA\n  RETURN TABLE (\n    SELECT Athlete.lastname, Record.venue, Record.whenRun\n    FROM Athlete, Record\n    WHERE Athlete.athleteId = Record.fkAthlete\n    ORDER BY whenRun\n  )\n'''\ndef result = []\nsql.eachRow('CALL SELECT_ATHLETE_RECORD()') {\n  result << \"$it.lastname $it.venue $it.whenRun\"\n}\nassert result == [\n    'da Costa Berlin 1998-09-20',\n    'Khannouchi Chicago 1999-10-24',\n    'Khannouchi London 2002-04-14',\n    'Tergat Berlin 2003-09-28'\n]\n"
  },
  {
    "path": "listings/chap13/Listing_13_16_StoredProcParam.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\n\nsql.execute '''\n  CREATE FUNCTION FULL_NAME (p_lastname VARCHAR(64))\n  RETURNS VARCHAR(100)\n  READS SQL DATA\n  BEGIN ATOMIC\n    DECLARE ans VARCHAR(100);\n    SELECT CONCAT(firstname, ' ', lastname) INTO ans\n    FROM Athlete WHERE lastname = p_lastname;\n    RETURN ans;\n  END\n'''\n\nassert sql.firstRow(\"{? = call FULL_NAME(?)}\",\n    ['Tergat'])[0] == 'Paul Tergat'\n"
  },
  {
    "path": "listings/chap13/Listing_13_17_StoredProcInOut.groovy",
    "content": "import groovy.sql.Sql\nimport util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\n\nsql.execute '''\n  CREATE PROCEDURE CONCAT_NAME (OUT fullname VARCHAR(100),\n    IN first VARCHAR(50), IN last VARCHAR(50))\n  BEGIN ATOMIC\n    SET fullname = CONCAT(first, ' ', last);\n  END\n'''\n\nsql.call(\"{call CONCAT_NAME(?, ?, ?)}\",\n    [Sql.VARCHAR, 'Paul', 'Tergat']) {\n  fullname -> assert fullname == 'Paul Tergat'\n}\n"
  },
  {
    "path": "listings/chap13/Listing_13_18_DataSetBasics.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\n\ndef athletes = sql.dataSet('Athlete')\n\ndef result = []\nathletes.each { result << it.firstname }                              //#1\nassert result == ['Paul', 'Khalid', 'Ronaldo']                        //#A\n\nathletes.add(\n    firstname: 'Paula',\n    lastname: 'Radcliffe',\n    dateOfBirth: '1973-12-17'\n)\n\nresult = athletes.rows().collect { it.firstname }                     //#2\nassert result == ['Paul', 'Khalid', 'Ronaldo', 'Paula']               //#B\n//#A Initially we have our three sample athletes\n//#B Confirm we now have four athletes\n//#1 Treating a SQL table like a list of map-like rows\n//#2 Using rows followed by collect\n"
  },
  {
    "path": "listings/chap13/Listing_13_19_DataSetFiltering.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\nDbUtil.enableLogging()\n\ndef athletes = sql.dataSet('Athlete')\n\nathletes.add(\n    firstname: 'Paula',\n    lastname: 'Radcliffe',\n    dateOfBirth: '1973-12-17'\n)\n\ndef query = athletes.findAll { it.firstname >= 'P' }\nquery = query.findAll { it.dateOfBirth > '1970-01-01' }\nquery = query.sort { it.dateOfBirth }\nquery = query.reverse()\nassert query.sql == 'select * from Athlete where firstname >= ? and ' +\n    'dateOfBirth > ? order by dateOfBirth DESC'\nassert query.parameters == ['P', '1970-01-01']\nassert query.rows()*.firstname == ['Paula', 'Ronaldo']\n"
  },
  {
    "path": "listings/chap13/Listing_13_20_DataSetViews.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\n\nsql.execute '''\n    DROP   VIEW AthleteRecord IF EXISTS;\n    CREATE VIEW AthleteRecord AS\n      SELECT * FROM Athlete LEFT OUTER JOIN Record\n        ON fkAthlete=athleteId;\n'''\n\ndef records = sql.dataSet('AthleteRecord').findAll {\n  it.firstname == 'Khalid'\n}\ndef result = records.rows().collect { \"$it.lastname $it.venue\" }\nassert ['Khannouchi London', 'Khannouchi Chicago'] == result\n"
  },
  {
    "path": "listings/chap13/Listing_13_21_DbHelper.txt",
    "content": "see: layering/DbHelper.groovy"
  },
  {
    "path": "listings/chap13/Listing_13_22_DataAccessObject.txt",
    "content": "see: layering/DataAccessObject.groovy"
  },
  {
    "path": "listings/chap13/Listing_13_23_AthleteDAO.txt",
    "content": "see: layering/AthleteDAO.groovy"
  },
  {
    "path": "listings/chap13/Listing_13_24_AthleteApplication.txt",
    "content": "see: layering/AthleteApplication.groovy"
  },
  {
    "path": "listings/chap13/Listing_13_25_AthleteAppMain.groovy",
    "content": "import layering.*\n\ndef app = new AthleteApplication()\napp.init()\napp.mainLoop()\n"
  },
  {
    "path": "listings/chap13/Listing_13_26_AthleteAppTest.groovy",
    "content": "import layering.*\n\ndef app = new AthleteApplication()\napp.init()\n\n// next line only for the benefit of alltests.groovy\ndef oldOut = System.out\n\nByteArrayOutputStream baos = captureSystemOut()\noverrideSystemIn()\ntry {\n    app.mainLoop()\n} finally {\n    // next line only for the benefit of alltests.groovy\n    System.setOut(oldOut)\n}\n\nverifyOutput(baos)\n\ndef captureSystemOut() {                           //#A\n    def baos = new ByteArrayOutputStream()\n    System.out = new PrintStream(baos)\n    baos\n}\n\ndef overrideSystemIn() {                           //#B\n    System.in = new ByteArrayInputStream('''\\\ncreate Paul Tergat 1969-06-17\ncreate Khalid Khannouchi\nupdate 1 dateOfBirth 1971-12-22\nsort firstname\ndelete 1\nexit\n'''.bytes)\n}\n\ndef verifyOutput(output) {\n    assert output.toString().readLines()*.trim().join('\\n') == '''\ncommands: create list update delete sort exit\n1 Athlete(s) in DB:\nid firstname  lastname     dateOfBirth\n0: Paul       Tergat       1969-06-17\n\ncommands: create list update delete sort exit\n2 Athlete(s) in DB:\nid firstname  lastname     dateOfBirth\n0: Paul       Tergat       1969-06-17\n1: Khalid     Khannouchi   null\n\ncommands: create list update delete sort exit\n1 row(s) updated\n2 Athlete(s) in DB:\nid firstname  lastname     dateOfBirth\n0: Paul       Tergat       1969-06-17\n1: Khalid     Khannouchi   1971-12-22\n\ncommands: create list update delete sort exit\n2 Athlete(s) in DB:\nid firstname  lastname     dateOfBirth\n1: Khalid     Khannouchi   1971-12-22\n0: Paul       Tergat       1969-06-17\n\ncommands: create list update delete sort exit\n1 row(s) deleted\n1 Athlete(s) in DB:\nid firstname  lastname     dateOfBirth\n0: Paul       Tergat       1969-06-17\n\ncommands: create list update delete sort exit'''\n}\n//#A Capture standard output stream for testing\n//#B Replace standard input stream with canned input\n"
  },
  {
    "path": "listings/chap13/Listing_13_27_MongoAthletes.groovy",
    "content": "@Grab('com.gmongo:gmongo:1.3')\nimport com.gmongo.GMongo\nimport com.mongodb.util.JSON\nimport groovy.transform.Field\n\n@Field db = new GMongo().getDB('athletes')\ndb.athletes.drop()\ndb.athletes << [first: 'Paul', last: 'Tergat', dob: '1969-06-17', records: [\n        [time: 2 * 60 * 60 + 4 * 60 + 55,\n         venue: 'Berlin', when: '2003-09-28']\n]]\n\ndef insertAthlete(first, last, dob) {\n    db.athletes << [first: first, last: last, dob: dob]\n}\n\ndef insertRecord(h, m, s, venue, date, lastname) {\n    db.athletes.update(\n            [last: lastname],\n            [$addToSet: [records: [time: h * 60 * 60 + m * 60 + s,\n                                venue: venue, when: date]]]\n    )\n}\n\ninsertAthlete('Khalid', 'Khannouchi', '1971-12-22')\ninsertAthlete('Ronaldo', 'da Costa', '1970-06-07')\n\ninsertRecord(2, 5, 38, 'London', '2002-04-14', 'Khannouchi')\ninsertRecord(2, 5, 42, 'Chicago', '1999-10-24', 'Khannouchi')\ninsertRecord(2, 6, 05, 'Berlin', '1998-09-20', 'da Costa')\n\ndef radcliffe = \"\"\"{\n    first: 'Paula',\n    last: 'Radcliffe',\n    dob: '1973-12-17',\n    records: [\n        {time: ${2 * 60 * 60 + 15 * 60 + 25},\n            venue: 'London', when: '2003-04-13'}\n    ]\n}\"\"\"\n\ndb.athletes << JSON.parse(radcliffe)\n\nassert db.athletes.count == 4\ndb.athletes.find().each {\n    println \"$it._id $it.last ${it.records.size()}\"\n}\n//516b15fc2b10a15fa09331f2 Tergat 1\n//516b15fc2b10a15fa09331f3 Khannouchi 2\n//516b15fc2b10a15fa09331f4 da Costa 1\n//516b15fc2b10a15fa09331f5 Radcliffe 1\n\ndef londonAthletes = db.athletes.find('records.venue': 'London')*.first\nassert londonAthletes == ['Khalid', 'Paula']\n\ndef youngAthletes = db.athletes.aggregate(\n        [$project: [first: 1, dob: 1]],\n        [$match: [dob: [$gte: '1970-01-01']]],\n        [$sort: [dob: -1]]\n)\n\nassert youngAthletes.results()*.first == ['Paula', 'Khalid', 'Ronaldo']\n"
  },
  {
    "path": "listings/chap13/Listing_13_28_NeoAthletes.groovy",
    "content": "@Grab('org.neo4j:neo4j-kernel:2.1.6')\n@Grab('org.neo4j:neo4j-lucene-index:2.1.6;transitive=false')\n@Grab('org.apache.lucene:lucene-core:3.6.2')\nimport org.neo4j.graphdb.*\nimport org.neo4j.graphdb.traversal.*\nimport static util.Neo4jUtil.*\nimport static util.MarathonRelationships.*\n\ndef db = create()\ndef tx = null\ndef athlete1, athlete2, athlete3, athlete4\ndef record1, record2a, record2b, record3, record4a, record4b\ntry {\n  tx = db.beginTx()\n\n  athlete1 = db.createNode()                                        //#A\n  athlete1.first = 'Paul'                                           //#A\n  athlete1.last = 'Tergat'                                          //#A\n  athlete1.dob = '1969-06-17'                                       //#A\n\n  record1 = db.createNode()                                         //#B\n  record1.time = 2 * 60 * 60 + 4 * 60 + 55                          //#B\n  record1.venue = 'Berlin'                                          //#B\n  record1.when = '2003-09-28'                                       //#B\n\n  athlete1.set(record1)\n\n  assert 'Paul Tergat won the Berlin marathon on 2003-09-28' ==\n      \"$athlete1.first $athlete1.last won the \" +\n      \"$record1.venue marathon on $record1.when\"\n\n  athlete2 = insertAthlete(                                         //#C\n      db, 'Khalid', 'Khannouchi', '1971-12-22')                     //#C\n  record2a = insertRecord(                                          //#C\n      db, 2, 5, 38, 'London', '2002-04-14', athlete2)               //#C\n  record2b = insertRecord(                                          //#C\n      db, 2, 5, 42, 'Chicago', '1999-10-24', athlete2)              //#C\n\n  athlete3 = insertAthlete(db, 'Ronaldo', 'da Costa', '1970-06-07')\n  record3 = insertRecord(db, 2, 6, 5, 'Berlin', '1998-09-20', athlete3)\n\n  athlete4 = insertAthlete(db, 'Paula', 'Radcliffe', '1973-12-17')\n  record4a = insertRecord(\n      db, 2, 17, 18, 'Chicago', '2002-10-13', athlete4)\n  record4b = insertRecord(\n      db, 2, 15, 25, 'London', '2003-04-13', athlete4)\n\n  def allAthletes = [athlete1, athlete2, athlete3, athlete4]        //#D\n  def londonRecords = allAthletes.findAll { athlete ->              //#D\n    athlete.getRelationships(set).any {       //#D\n      record -> record.getOtherNode(athlete).venue == 'London'      //#D\n    }                                                               //#D\n  }                                                                 //#D\n  assert londonRecords*.last == ['Khannouchi', 'Radcliffe']\n\n  record2b.broke(record3)                                           //#E\n  record2a.broke(record2b)                                          //#E\n  record1.broke(record2a)                                           //#E\n  record4b.broke(record4a)                                          //#E\n\n  def result = []                                                   //#F\n  for (Path p in db.traversalDescription().breadthFirst().          //#F\n      relationships(broke).                                         //#F\n      evaluator(Evaluators.fromDepth(1)).                           //#F\n      uniqueness(Uniqueness.NONE).                                  //#F\n      traverse(record3)) {                                          //#F\n    def newRecord = p.endNode()                                     //#F\n    result << \"$newRecord.venue $newRecord.when\"                    //#F\n  }                                                                 //#F\n  def expected = ['Chicago 1999-10-24',\n                  'London 2002-04-14',\n                  'Berlin 2003-09-28']\n  assert expected == result\n\n  tx.success()\n} finally {\n  tx?.close()\n  // for the benefit of alltests, don't wait for shutdown hook\n  db?.shutdown()\n}\n//#A Create athlete1 by hand\n//#B Create record1 by hand\n//#C Create using utility methods\n//#D Find athletes holding a record set in London\n//#E Additional graph edges of interest\n//#F Find world records superseding record3"
  },
  {
    "path": "listings/chap13/Listing_13_29_NeoGremlin.groovy",
    "content": "@Grab('org.neo4j:neo4j-kernel:2.1.6')\n@Grab('org.neo4j:neo4j-management:2.1.6')\n@Grab('org.neo4j:neo4j-cypher:2.1.6;transitive=false')\n@Grab('org.neo4j:neo4j-cypher-commons:2.1.6;transitive=false')\n@Grab('org.neo4j:neo4j-cypher-compiler-1.9:2.0.4;transitive=false')\n@Grab('org.neo4j:neo4j-cypher-compiler-2.0:2.0.4;transitive=false')\n@Grab('org.neo4j:neo4j-cypher-compiler-2.1:2.1.6;transitive=false')\n@Grab('org.neo4j:neo4j-lucene-index:2.1.6;transitive=false')\n@Grab('org.apache.lucene:lucene-core:3.6.2')\n@Grab('com.tinkerpop.gremlin:gremlin-groovy:2.6.0;transitive=false')\n@Grab('com.tinkerpop.gremlin:gremlin-java:2.6.0;transitive=false')\n@Grab('com.tinkerpop.blueprints:\\\nblueprints-neo4j2-graph:2.6.0;transitive=false')\n@Grab('commons-configuration:commons-configuration:1.6')\n@Grab('com.tinkerpop.blueprints:blueprints-core:2.6.0;transitive=false')\n@Grab('com.tinkerpop:pipes:2.6.0;transitive=false')\n@Grab('org.parboiled:parboiled-scala_2.10:1.1.6;transitive=false')\n@Grab('org.parboiled:parboiled-core:1.1.6')\n@Grab('org.scala-lang:scala-library:2.10.4')\n@Grab('com.googlecode.concurrentlinkedhashmap:\\\nconcurrentlinkedhashmap-lru:1.4.1')\n@GrabExclude('junit:junit')\n@GrabExclude('org.hamcrest:hamcrest-all')\n@GrabExclude('org.mockito:mockito-core')\n\nimport com.tinkerpop.blueprints.Graph\nimport com.tinkerpop.blueprints.impls.neo4j2.Neo4j2Graph\nimport com.tinkerpop.gremlin.groovy.Gremlin\nimport static util.Neo4jUtil.*\n\ndef db = create()\ndef tx = null\ndef athlete1, athlete2, athlete3, athlete4\ndef record1, record2a, record2b, record3, record4a, record4b\n\nGremlin.load()\n\ntry {\n    tx = db.beginTx()\n\n    // create athlete1 .. athlete4\n    athlete1 = insertAthlete(db, 'Paul', 'Tergat', '1969-06-17')\n    record1 = insertRecord(\n        db, 2, 4, 55, 'Berlin', '2003-09-28', athlete1)\n\n    athlete2 = insertAthlete(db, 'Khalid', 'Khannouchi', '1971-12-22')\n    record2a = insertRecord(\n        db, 2, 5, 38, 'London', '2002-04-14', athlete2)\n    record2b = insertRecord(\n        db, 2, 5, 42, 'Chicago', '1999-10-24', athlete2)\n\n    athlete3 = insertAthlete(db, 'Ronaldo', 'da Costa', '1970-06-07')\n    record3 = insertRecord(\n        db, 2, 6, 5, 'Berlin', '1998-09-20', athlete3)\n\n    athlete4 = insertAthlete(db, 'Paula', 'Radcliffe', '1973-12-17')\n    record4a = insertRecord(\n        db, 2, 17, 18, 'Chicago', '2002-10-13', athlete4)\n    record4b = insertRecord(\n        db, 2, 15, 25, 'London', '2003-04-13', athlete4)\n\n    record2b.broke(record3)\n    record2a.broke(record2b)\n    record1.broke(record2a)\n    record4b.broke(record4a)\n\n    Graph g = new Neo4j2Graph(db)\n\n    def pretty = { it.collect { \"$it.venue $it.when\" }.join(', ') }\n    def results = []\n    g.V('venue', 'London').fill(results)\n    println 'London world records: ' + pretty(results)\n\n    results = []\n    g.V('venue', 'London').in('broke').fill(results)\n    println 'World records after London: ' + pretty(results)\n\n    results = []\n    def emitAll = { true }\n    def forever = { true }\n    def berlin98 = { it.venue == 'Berlin' &&\n            it.when.startsWith('1998') }\n    g.V.filter(berlin98).in('broke').\n            loop(1, forever, emitAll).fill(results)\n    println 'World records after Berlin 1998: ' + pretty(results)\n    tx.success()\n} finally {\n    tx?.close()\n\n}\n"
  },
  {
    "path": "listings/chap13/extra_NeoGremlinGraph.groovy",
    "content": "/* */\n@Grab('org.neo4j:neo4j-kernel:2.1.4')\n@Grab('org.neo4j:neo4j-management:2.1.4')\n@Grab('org.neo4j:neo4j-cypher:2.1.4;transitive=false')\n@Grab('org.neo4j:neo4j-cypher-commons:2.1.4')\n@Grab('org.neo4j:neo4j-cypher-compiler-1.9:2.0.4')\n@Grab('org.neo4j:neo4j-cypher-compiler-2.0:2.0.4')\n@Grab('org.neo4j:neo4j-cypher-compiler-2.1:2.1.4')\n@Grab('org.neo4j:neo4j-lucene-index:2.1.4;transitive=false')\n@Grab('org.apache.lucene:lucene-core:3.6.2')\n@Grab('com.tinkerpop.gremlin:gremlin-groovy:2.6.0;transitive=false')\n@Grab('com.tinkerpop.gremlin:gremlin-java:2.6.0;transitive=false')\n@Grab('com.tinkerpop.blueprints:blueprints-neo4j2-graph:2.6.0;transitive=false')\n@Grab('commons-configuration:commons-configuration:1.6')\n@Grab('com.tinkerpop.blueprints:blueprints-core:2.6.0;transitive=false')\n@Grab('com.tinkerpop:pipes:2.6.0;transitive=false')\n//@Grab('codehaus-stax:stax:1.1.1')\n//@GrabResolver('https://repository.jboss.org/nexus/content/repositories/thirdparty-releases')\n//@GrabExclude('org.codehaus.groovy:groovy')\n@GrabExclude('junit:junit')\n@GrabExclude('org.hamcrest:hamcrest-all')\n@GrabExclude('org.mockito:mockito-core')\n/* */\nimport com.tinkerpop.blueprints.Graph\nimport com.tinkerpop.blueprints.impls.neo4j2.Neo4j2Graph\nimport com.tinkerpop.blueprints.util.io.graphml.GraphMLWriter\nimport com.tinkerpop.gremlin.groovy.Gremlin\nimport static util.Neo4jUtil.*\n\nprintln 'starting'\ndef db = create()\ndef tx = null\ndef athlete1, athlete2, athlete3, athlete4\ndef record1, record2a, record2b, record3, record4a, record4b\n\nprintln 'about to load'\nGremlin.load()\nprintln 'loaded'\n\ntry {\n    tx = db.beginTx()\n\n    // create athlete1 .. athlete4\n    athlete1 = insertAthlete(db, 'Paul', 'Tergat', '1969-06-17')\n    record1 = insertRecord(\n        db, 2, 4, 55, 'Berlin', '2003-09-28', athlete1)\n\n    athlete2 = insertAthlete(db, 'Khalid', 'Khannouchi', '1971-12-22')\n    record2a = insertRecord(\n        db, 2, 5, 38, 'London', '2002-04-14', athlete2)\n    record2b = insertRecord(\n        db, 2, 5, 42, 'Chicago', '1999-10-24', athlete2)\n\n    athlete3 = insertAthlete(db, 'Ronaldo', 'da Costa', '1970-06-07')\n    record3 = insertRecord(\n        db, 2, 6, 5, 'Berlin', '1998-09-20', athlete3)\n\n    athlete4 = insertAthlete(db, 'Paula', 'Radcliffe', '1973-12-17')\n    record4a = insertRecord(\n        db, 2, 17, 18, 'Chicago', '2002-10-13', athlete4)\n    record4b = insertRecord(\n        db, 2, 15, 25, 'London', '2003-04-13', athlete4)\n\n    record2b.broke(record3)\n    record2a.broke(record2b)\n    record1.broke(record2a)\n    record4b.broke(record4a)\n\n    Graph g = new Neo4j2Graph(db)\n\n    def writer = new GraphMLWriter(g)\n    def out = new FileOutputStream(\"/temp/athletes.graphml\")\n    writer.outputGraph(out)\n    writer.setNormalize(true)\n    out.close()\n    tx.success()\n} finally {\n    tx?.close()\n}\n"
  },
  {
    "path": "listings/chap13/layering/AthleteApplication.groovy",
    "content": "package layering\n\nclass AthleteApplication {\n  def helper = new DbHelper()                          //#1\n  def athleteDAO = new AthleteDAO(db: helper.db)       //#1\n  def sortBy = 'athleteId'                             //#1\n  def done = false\n\n  def init() { helper.executeDdl(athleteDAO) }         //#1\n\n  def exit() { done = true }\n\n  def sort(field) {\n    sortBy = field\n    list()\n  }\n\n  def create(first, last = null, dob = null) {\n    athleteDAO.create([first, last, dob])\n    list()\n  }\n\n  def list() {\n    def athletes = athleteDAO.all(sortBy)\n    println athletes.size() + ' Athlete(s) in DB: '\n    println 'id firstname  lastname     dateOfBirth'\n    athletes.each { athlete ->\n      println athlete.athleteId + ': ' +\n          athlete.firstname.padRight(10) + ' ' +\n          athlete.lastname.padRight(12) + ' ' +\n          athlete.dateOfBirth\n    }\n  }\n\n  def update(id, field, newValue) {\n    def count = athleteDAO.update(field, newValue, id)\n    println count + ' row(s) updated'\n    list()\n  }\n\n  def delete(id) {\n    def count = athleteDAO.delete(id)\n    println count + ' row(s) deleted'\n    list()\n  }\n\n  def mainLoop() {                                     //#2\n    def reader = System.in.newReader()\n    while (!done) {\n      println '\\ncommands: create list update delete sort exit'\n      def input = reader.readLine().tokenize()         //#A\n      def method = input.remove(0)                     //#A\n      this.\"$method\"(*input)                           //#A\n    }\n  }\n}\n//#1 Initialization\n//#2 Entry point\n//#A Commands are provided as methods, then arguments\n"
  },
  {
    "path": "listings/chap13/layering/AthleteDAO.groovy",
    "content": "package layering\n\nclass AthleteDAO extends DataAccessObject {\n  List getFields() {\n    return [\n        'firstname',   'VARCHAR(64)',\n        'lastname',    'VARCHAR(64)',\n        'dateOfBirth', 'DATE'\n    ]\n  }\n}\n"
  },
  {
    "path": "listings/chap13/layering/DataAccessObject.groovy",
    "content": "package layering\n\nabstract class DataAccessObject {\n  def db\n\n  abstract List getFields()                            //#1\n\n  def dataSet() { db.dataSet(tablename) }              //#2\n  def getIdField() { tablename.toLowerCase() + 'Id' }  //#2\n  private getWhereId() { \"WHERE $idField = ?\" }        //#2\n\n  String getTablename() {\n    def name = this.getClass().name\n    return name[name.lastIndexOf('.') + 1..-4]\n  }\n\n  def create(List args) {                              //#3\n    Map argMap = [:]\n    args.eachWithIndex { arg, i -> argMap[fieldNames[i]] = arg }\n    dataSet().add argMap\n  }\n\n  Map getSchema() {\n    Map result = [:]\n    fieldNames.each {\n      result[it] = fields[fields.indexOf(it) + 1]\n    }\n    return result\n  }\n\n  List getFieldNames() {\n    List result = []\n    0.step(fields.size(), 2) { result << fields[it] }\n    return result\n  }\n\n  def update(field, newValue, id) {\n    def stmt = \"UPDATE $tablename SET $field = ? ${getWhereId()}\"\n    db.executeUpdate stmt, [newValue, id]\n  }\n\n  def delete(id) {\n    def stmt = \"DELETE FROM $tablename ${getWhereId()}\"\n    db.executeUpdate stmt, [id]\n  }\n\n  def all(sortField) {                                 //#4\n    def selects = fieldNames + idField\n    def result = []\n    def stmt = \"SELECT \" + selects.join(',') +\n        \" FROM $tablename ORDER BY $sortField\"\n    db.eachRow(stmt.toString()) { rs ->\n      Map businessObject = [:]\n      selects.each { businessObject[it] = rs[it] }\n      result << businessObject\n    }\n    return result\n  }\n}\n//#1 Subclass implements this to provide field list\n//#2 Properties for use in SQL statements\n//#3 Create operation\n//#4 Sample read operation\n"
  },
  {
    "path": "listings/chap13/layering/DbHelper.groovy",
    "content": "package layering\n\n//@Grab('org.hsqldb:hsqldb:2.3.2')\nimport groovy.sql.Sql\nimport groovy.text.SimpleTemplateEngine as STE\n\nimport org.hsqldb.jdbc.JDBCDataSource\n\nclass DbHelper {\n  Sql db\n\n  DbHelper() {\n    db = new Sql(new JDBCDataSource(\n        database: 'jdbc:hsqldb:mem:GinA', user: 'sa', password: ''))\n  }\n\n  def simpleTemplate = new STE().createTemplate('''\nDROP   TABLE $name    IF EXISTS cascade;\nCREATE TABLE $name (\n    ${lowname}Id    INTEGER GENERATED BY DEFAULT AS IDENTITY,\n$fields\n);\n''')\n\n  def executeDdl(DataAccessObject dao) {\n    def template = simpleTemplate\n    def binding = [\n        name: dao.tablename,\n        lowname: dao.tablename.toLowerCase(),\n        fields: dao.schema.collect { key, val ->\n          \"    ${key.padRight(12)} $val\" }.join(\",\\n\")\n    ]\n    def stmt = template.make(binding).toString()\n    db.execute stmt\n  }\n}\n"
  },
  {
    "path": "listings/chap13/marathon/active_tx_log",
    "content": "tm_tx_log.1"
  },
  {
    "path": "listings/chap13/marathon/messages.log",
    "content": "2015-02-01 16:39:29.276+0000 INFO  [org.neo4j]: No locking implementation specified, defaulting to 'community'\n2015-02-01 16:39:29.352+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics START ---\n2015-02-01 16:39:29.353+0000 INFO  [org.neo4j]: Neo4j Kernel properties:\n    neostore.propertystore.db.mapped_memory=1326M\n    neostore.nodestore.db.mapped_memory=368M\n    neostore.relationshipstore.db.mapped_memory=1624M\n    neostore.propertystore.db.strings.mapped_memory=1127M\n    store_dir=marathon\n    neostore.propertystore.db.arrays.mapped_memory=1277M\n    ephemeral=false\n2015-02-01 16:39:29.355+0000 INFO  [org.neo4j]: Diagnostics providers:\n    org.neo4j.kernel.configuration.Config\n    org.neo4j.kernel.info.DiagnosticsManager\n    SYSTEM_MEMORY\n    JAVA_MEMORY\n    OPERATING_SYSTEM\n    JAVA_VIRTUAL_MACHINE\n    CLASSPATH\n    LIBRARY_PATH\n    SYSTEM_PROPERTIES\n    NETWORK\n2015-02-01 16:39:29.355+0000 INFO  [org.neo4j]: System memory information:\n    Total Physical memory: 16.00 GB\n    Free Physical memory: 2.75 GB\n    Committed virtual memory: 6.80 GB\n    Total swap space: 1.00 GB\n    Free swap space: 981.75 MB\n2015-02-01 16:39:29.359+0000 INFO  [org.neo4j]: JVM memory information:\n    Free  memory: 186.19 MB\n    Total memory: 244.00 MB\n    Max   memory: 3.56 GB\n    Garbage Collector: PS Scavenge: [PS Eden Space, PS Survivor Space]\n    Garbage Collector: PS MarkSweep: [PS Eden Space, PS Survivor Space, PS Old Gen, PS Perm Gen]\n    Memory Pool: Code Cache (Non-heap memory): committed=4.06 MB, used=4.00 MB, max=48.00 MB, threshold=0.00 B\n    Memory Pool: PS Eden Space (Heap memory): committed=63.00 MB, used=29.61 MB, max=1.31 GB, threshold=?\n    Memory Pool: PS Survivor Space (Heap memory): committed=10.50 MB, used=10.49 MB, max=10.50 MB, threshold=?\n    Memory Pool: PS Old Gen (Heap memory): committed=170.50 MB, used=17.71 MB, max=2.67 GB, threshold=0.00 B\n    Memory Pool: PS Perm Gen (Non-heap memory): committed=29.00 MB, used=28.87 MB, max=82.00 MB, threshold=0.00 B\n2015-02-01 16:39:29.367+0000 INFO  [org.neo4j]: Operating system information:\n    Operating System: Mac OS X; version: 10.10.2; arch: x86_64; cpus: 8\n    Max number of file descriptors: 10240\n    Number of open file descriptors: 78\n    Process id: 4500@Dierk-Konigs-MacBook-Pro.local\n    Byte order: LITTLE_ENDIAN\n    Local timezone: Europe/Zurich\n2015-02-01 16:39:29.369+0000 INFO  [org.neo4j]: JVM information:\n    VM Name: Java HotSpot(TM) 64-Bit Server VM\n    VM Vendor: Oracle Corporation\n    VM Version: 24.51-b03\n    JIT compiler: HotSpot 64-Bit Tiered Compilers\n    VM Arguments: [-Dscript.name=/Users/dierkkoenig/.gvm/groovy/2.4.0/bin/groovy, -Dprogram.name=groovy, -Dgroovy.starter.conf=/Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf, -Dgroovy.home=/Users/dierkkoenig/.gvm/groovy/2.4.0, -Dtools.jar=/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar]\n2015-02-01 16:39:29.370+0000 INFO  [org.neo4j]: Java classpath:\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/qdox-1.12.1.jar\n     [loader.3] file:/System/Library/Java/Extensions/dns_sd.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jcommander-1.47.jar\n     [loader.2] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-1.9.4.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jce.jar\n     [loader.3] file:/Users/dierkkoenig/Library/Java/Extensions/libJNPRAuthKit.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/bsf-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/MRJToolkit.jar\n     [loader.3] file:/opt/subversion/lib/libsvnjavahl-1.0.0.0.dylib\n     [loader.3] file:/System/Library/Java/Extensions/vecmath.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/sunrsasign.jar\n     [loader.3] file:/System/Library/Java/Extensions/libmlib_jai.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-groovysh-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-antlr-1.9.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/xmlpull-1.1.3.1.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-bsf-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-nio-2.4.0.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunec.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/servlet-api-2.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-sql-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-xml-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3D.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jsp-api-2.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/mlibwrapper_jai.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-primitive-collections/jars/neo4j-primitive-collections-2.1.6.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.lucene/lucene-core/jars/lucene-core-3.6.2.jar\n     [loader.3] file:/Library/Java/Extensions/librxtxSerial.jnilib\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/localedata.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/charsets.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-ant-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-test-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DAudio.jnilib\n     [loader.3] file:/System/Library/Java/Extensions/libAppleScriptEngine.jnilib\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jfr.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3daudio.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-groovydoc-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-jmx-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DUtils.jnilib\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-kernel/jars/neo4j-kernel-2.1.6.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dcore.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jansi-1.11.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/openbeans-1.0.jar\n     [loader.3] file:/usr/lib/java/libjdns_sd.jnilib\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-junit-1.9.4.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jsse.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jline-2.12.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/zipfs.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dutils.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/classes\n     [loader.3] file:/System/Library/Java/Extensions/jai_core.jar\n     [loader.1] file:/projects/git/regina/listings/chap13/./\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ivy-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-lucene-index/jars/neo4j-lucene-index-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-json-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.groovy/grapes/org.hsqldb/hsqldb/jars/hsqldb-2.3.2.jar\n     [loader.3] file:/System/Library/Java/Extensions/jai_codec.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-console-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-templates-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jsr166y-1.7.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-swing-2.4.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/resources.jar\n     [loader.3] file:/Library/Java/Extensions/RXTXcomm.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/hamcrest-core-1.3.jar\n     [loader.1] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-launcher-1.9.4.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.geronimo.specs/geronimo-jta_1.1_spec/jars/geronimo-jta_1.1_spec-1.1.1.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/dnsns.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-docgenerator-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/multiverse-core-0.7.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/commons-logging-1.2.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/rt.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/xstream-1.4.7.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/commons-cli-1.2.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-jsr223-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/junit-4.12.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-testng-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-servlet-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/AppleScriptEngine.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/testng-6.8.13.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/gpars-1.2.1.jar\n2015-02-01 16:39:29.373+0000 INFO  [org.neo4j]: Library path:\n    /Users/dierkkoenig/Library/Java/Extensions\n    /Library/Java/Extensions\n    /Network/Library/Java/Extensions\n    /System/Library/Java/Extensions\n    /usr/lib/java\n    /projects/git/regina/listings/chap13\n2015-02-01 16:39:29.373+0000 INFO  [org.neo4j]: System.properties:\n    sun.boot.library.path = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib\n    user.country.format = CH\n    gopherProxySet = false\n    path.separator = :\n    file.encoding.pkg = sun.io\n    user.country = DE\n    sun.java.launcher = SUN_STANDARD\n    sun.os.patch.level = unknown\n    program.name = groovy\n    user.dir = /projects/git/regina/listings/chap13\n    tools.jar = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n    sun.jnu.encoding = UTF-8\n    script.name = /Users/dierkkoenig/.gvm/groovy/2.4.0/bin/groovy\n    sun.management.compiler = HotSpot 64-Bit Tiered Compilers\n    http.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    user.home = /Users/dierkkoenig\n    user.timezone = Europe/Zurich\n    file.encoding = UTF-8\n    user.name = dierkkoenig\n    sun.java.command = org.codehaus.groovy.tools.GroovyStarter --main groovy.ui.GroovyMain --conf /Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf --classpath . ../../test\n    sun.arch.data.model = 64\n    user.language = de\n    awt.toolkit = sun.lwawt.macosx.LWCToolkit\n    file.separator = /\n    sun.io.unicode.encoding = UnicodeBig\n    sun.cpu.endian = little\n    groovy.starter.conf = /Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf\n    socksNonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    ftp.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    groovy.home = /Users/dierkkoenig/.gvm/groovy/2.4.0\n    sun.cpu.isalist = \n2015-02-01 16:39:29.373+0000 INFO  [org.neo4j]: Network information:\n    Interface awdl0:\n        address: fe80:0:0:0:b49d:fbff:fe48:bef5%10\n    Interface en0:\n        address: fe80:0:0:0:2acf:e9ff:fe19:ca6d%5\n        address: 10.0.1.19\n    Interface lo0:\n        address: fe80:0:0:0:0:0:0:1%1\n        address: 0:0:0:0:0:0:0:1\n        address: 127.0.0.1\n2015-02-01 16:39:29.374+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics END ---\n2015-02-01 16:39:29.407+0000 INFO  [org.neo4j]: Creating new db @ marathon/neostore\n2015-02-01 16:39:29.433+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-02-01 16:39:29.434+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-02-01 16:39:29.434+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db.names hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.436+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.439+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-02-01 16:39:29.440+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-02-01 16:39:29.440+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db.names hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.440+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.444+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-02-01 16:39:29.444+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-02-01 16:39:29.445+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-02-01 16:39:29.445+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-02-01 16:39:29.445+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.strings] brickCount=0 brickSize=1181696b mappedMem=1181745152b (storeSize=128b)\n2015-02-01 16:39:29.446+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index.keys] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-02-01 16:39:29.446+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-02-01 16:39:29.446+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.arrays] brickCount=0 brickSize=1339008b mappedMem=1339031552b (storeSize=128b)\n2015-02-01 16:39:29.449+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db] brickCount=0 brickSize=13904084b mappedMem=1390411776b (storeSize=0b)\n2015-02-01 16:39:29.452+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipstore.db] brickCount=0 brickSize=17028866b mappedMem=1702887424b (storeSize=0b)\n2015-02-01 16:39:29.452+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db.labels] brickCount=0 brickSize=0b mappedMem=0b (storeSize=68b)\n2015-02-01 16:39:29.454+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db] brickCount=0 brickSize=3858750b mappedMem=385875968b (storeSize=0b)\n2015-02-01 16:39:29.455+0000 INFO  [org.neo4j]: [marathon/neostore.schemastore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=64b)\n2015-02-01 16:39:29.457+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipgroupstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=25b)\n2015-02-01 16:39:29.458+0000 INFO  [org.neo4j]: [marathon/neostore] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-02-01 16:39:29.463+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db.names hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.463+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.464+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db.names hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.465+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.465+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.strings hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.466+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index.keys hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.466+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.467+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.arrays hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.468+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.468+0000 INFO  [org.neo4j]: marathon/neostore.relationshipstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.469+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db.labels hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.470+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.470+0000 INFO  [org.neo4j]: marathon/neostore.schemastore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.471+0000 INFO  [org.neo4j]: marathon/neostore.relationshipgroupstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:29.472+0000 INFO  [org.neo4j]: marathon/neostore hit=0 miss=10 switches=0 ooe=0\n2015-02-01 16:39:29.479+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-02-01 16:39:29.479+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-02-01 16:39:29.480+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-02-01 16:39:29.480+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-02-01 16:39:29.480+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.strings] brickCount=0 brickSize=1181696b mappedMem=1181745152b (storeSize=128b)\n2015-02-01 16:39:29.481+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index.keys] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-02-01 16:39:29.481+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-02-01 16:39:29.481+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.arrays] brickCount=0 brickSize=1339008b mappedMem=1339031552b (storeSize=128b)\n2015-02-01 16:39:29.481+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db] brickCount=0 brickSize=13904084b mappedMem=1390411776b (storeSize=0b)\n2015-02-01 16:39:29.482+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipstore.db] brickCount=0 brickSize=17028866b mappedMem=1702887424b (storeSize=0b)\n2015-02-01 16:39:29.482+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db.labels] brickCount=0 brickSize=0b mappedMem=0b (storeSize=68b)\n2015-02-01 16:39:29.482+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db] brickCount=0 brickSize=3858750b mappedMem=385875968b (storeSize=0b)\n2015-02-01 16:39:29.482+0000 INFO  [org.neo4j]: [marathon/neostore.schemastore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=64b)\n2015-02-01 16:39:29.483+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipgroupstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=25b)\n2015-02-01 16:39:29.483+0000 INFO  [org.neo4j]: [marathon/neostore] brickCount=0 brickSize=0b mappedMem=0b (storeSize=81b)\n2015-02-01 16:39:29.548+0000 INFO  [org.neo4j]: No lucene scan store index found, this might just be first use. Preparing to rebuild.\n2015-02-01 16:39:29.573+0000 INFO  [org.neo4j]: No lucene scan store index found, this might just be first use. Preparing to rebuild.\n2015-02-01 16:39:29.693+0000 INFO  [org.neo4j]: Opened logical log [marathon/nioneo_logical.log.1] version=0, lastTxId=1 (clean)\n2015-02-01 16:39:29.696+0000 INFO  [org.neo4j]: Rebuilding lucene scan store, this may take a while\n2015-02-01 16:39:29.697+0000 INFO  [org.neo4j]: Lucene scan store rebuilt (roughly -1 nodes)\n2015-02-01 16:39:29.699+0000 INFO  [org.neo4j]: TM new log: tm_tx_log.1\n2015-02-01 16:39:29.703+0000 INFO  [org.neo4j]: Kernel health set to OK\n2015-02-01 16:39:29.712+0000 INFO  [org.neo4j]: Opened logical log [marathon/index/lucene.log.1] version=0, lastTxId=1 (clean)\n2015-02-01 16:39:29.716+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions START ---\n2015-02-01 16:39:29.716+0000 INFO  [org.neo4j]: Graph Database: org.neo4j.kernel.EmbeddedGraphDatabase StoreId{creationTime=1422808769411, randomId=1762119504651947014, storeVersion=14406081294923270, upgradeTime=1422808769411, upgradeId=1762119504651947014}\n2015-02-01 16:39:29.718+0000 INFO  [org.neo4j]: Kernel version: Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6\n2015-02-01 16:39:29.718+0000 INFO  [org.neo4j]: Neo4j component versions:\n2015-02-01 16:39:29.719+0000 INFO  [org.neo4j]:   Neo4j - Lucene Index (neo4j-lucene-index), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-01 16:39:29.719+0000 INFO  [org.neo4j]:   Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-01 16:39:29.719+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions END ---\n2015-02-01 16:39:29.722+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS START ---\n2015-02-01 16:39:29.722+0000 INFO  [org.neo4j]: Store versions:\n    Store versions:\n      NeoStore v0.A.3\n      SchemaStore v0.A.3\n      NodeStore v0.A.3\n      RelationshipStore v0.A.3\n      RelationshipTypeStore v0.A.3\n      LabelTokenStore v0.A.3\n      PropertyStore v0.A.3\n      PropertyIndexStore v0.A.3\n      StringPropertyStore v0.A.3\n      ArrayPropertyStore v0.A.3\n      RelationshipGroupStore v0.A.3\n2015-02-01 16:39:29.722+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS END ---\n2015-02-01 16:39:29.723+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE START ---\n2015-02-01 16:39:29.723+0000 INFO  [org.neo4j]: Id usage:\n    Id usage:\n      SchemaStore: used=1 high=0\n      NodeStore: used=0 high=-1\n      RelationshipStore: used=0 high=-1\n      RelationshipTypeStore: used=0 high=-1\n      LabelTokenStore: used=0 high=-1\n      PropertyStore: used=0 high=-1\n      PropertyIndexStore: used=0 high=-1\n      StringPropertyStore: used=1 high=0\n      ArrayPropertyStore: used=1 high=0\n      RelationshipGroupStore: used=1 high=0\n2015-02-01 16:39:29.723+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE END ---\n2015-02-01 16:39:29.723+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS START ---\n2015-02-01 16:39:29.723+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS END ---\n2015-02-01 16:39:29.724+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles START ---\n2015-02-01 16:39:29.724+0000 INFO  [org.neo4j]: Disk space on partition (Total / Free / Free %): 499082485760 / 175066800128 / 35\nStorage files: (filename : modification date - size)\n      active_tx_log: 2015-02-01T17:39:29+0100 - 11.00 B\n      index:\n        lucene-store.db: 2015-02-01T17:39:29+0100 - 40.00 B\n        lucene.log.1: 2015-02-01T17:39:29+0100 - 16.00 B\n        lucene.log.active: 2015-02-01T17:39:29+0100 - 4.00 B\n      - Total: 2015-02-01T17:39:29+0100 - 60.00 B\n      lock: 2015-02-01T17:39:29+0100 - 0.00 B\n      messages.log: 2015-02-01T17:39:29+0100 - 22.22 kB\n      neostore: 2015-02-01T17:39:29+0100 - 81.00 B\n      neostore.id: 2015-02-01T17:39:29+0100 - 9.00 B\n      neostore.labeltokenstore.db: 2015-02-01T17:39:29+0100 - 0.00 B\n      neostore.labeltokenstore.db.id: 2015-02-01T17:39:29+0100 - 9.00 B\n      neostore.labeltokenstore.db.names: 2015-02-01T17:39:29+0100 - 38.00 B\n      neostore.labeltokenstore.db.names.id: 2015-02-01T17:39:29+0100 - 9.00 B\n      neostore.nodestore.db: 2015-02-01T17:39:29+0100 - 0.00 B\n      neostore.nodestore.db.id: 2015-02-01T17:39:29+0100 - 9.00 B\n      neostore.nodestore.db.labels: 2015-02-01T17:39:29+0100 - 68.00 B\n      neostore.nodestore.db.labels.id: 2015-02-01T17:39:29+0100 - 9.00 B\n      neostore.propertystore.db: 2015-02-01T17:39:29+0100 - 0.00 B\n      neostore.propertystore.db.arrays: 2015-02-01T17:39:29+0100 - 128.00 B\n      neostore.propertystore.db.arrays.id: 2015-02-01T17:39:29+0100 - 9.00 B\n      neostore.propertystore.db.id: 2015-02-01T17:39:29+0100 - 9.00 B\n      neostore.propertystore.db.index: 2015-02-01T17:39:29+0100 - 0.00 B\n      neostore.propertystore.db.index.id: 2015-02-01T17:39:29+0100 - 9.00 B\n      neostore.propertystore.db.index.keys: 2015-02-01T17:39:29+0100 - 38.00 B\n      neostore.propertystore.db.index.keys.id: 2015-02-01T17:39:29+0100 - 9.00 B\n      neostore.propertystore.db.strings: 2015-02-01T17:39:29+0100 - 128.00 B\n      neostore.propertystore.db.strings.id: 2015-02-01T17:39:29+0100 - 9.00 B\n      neostore.relationshipgroupstore.db: 2015-02-01T17:39:29+0100 - 25.00 B\n      neostore.relationshipgroupstore.db.id: 2015-02-01T17:39:29+0100 - 9.00 B\n      neostore.relationshipstore.db: 2015-02-01T17:39:29+0100 - 0.00 B\n      neostore.relationshipstore.db.id: 2015-02-01T17:39:29+0100 - 9.00 B\n      neostore.relationshiptypestore.db: 2015-02-01T17:39:29+0100 - 0.00 B\n      neostore.relationshiptypestore.db.id: 2015-02-01T17:39:29+0100 - 9.00 B\n      neostore.relationshiptypestore.db.names: 2015-02-01T17:39:29+0100 - 38.00 B\n      neostore.relationshiptypestore.db.names.id: 2015-02-01T17:39:29+0100 - 9.00 B\n      neostore.schemastore.db: 2015-02-01T17:39:29+0100 - 64.00 B\n      neostore.schemastore.db.id: 2015-02-01T17:39:29+0100 - 9.00 B\n      nioneo_logical.log.1: 2015-02-01T17:39:29+0100 - 16.00 B\n      nioneo_logical.log.active: 2015-02-01T17:39:29+0100 - 4.00 B\n      schema:\n        label:\n          lucene:\n            write.lock: 2015-02-01T17:39:29+0100 - 0.00 B\n          - Total: 2015-02-01T17:39:29+0100 - 0.00 B\n        - Total: 2015-02-01T17:39:29+0100 - 0.00 B\n      - Total: 2015-02-01T17:39:29+0100 - 0.00 B\n      store_lock: 2015-02-01T17:39:29+0100 - 0.00 B\n      tm_tx_log.1: 2015-02-01T17:39:29+0100 - 0.00 B\n2015-02-01 16:39:29.732+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles END ---\n2015-02-01 16:39:29.791+0000 INFO  [org.neo4j]: Database is now ready\n2015-02-01 16:39:30.044+0000 INFO  [org.neo4j]: Shutdown started\n2015-02-01 16:39:30.044+0000 INFO  [org.neo4j]: Database is now unavailable\n2015-02-01 16:39:30.046+0000 INFO  [org.neo4j]: Closed log marathon/index/lucene.log\n2015-02-01 16:39:30.046+0000 INFO  [org.neo4j]: TM shutting down\n2015-02-01 16:39:30.052+0000 INFO  [org.neo4j]: Closed log marathon/nioneo_logical.log\n2015-02-01 16:39:30.053+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db.names hit=0 miss=2 switches=0 ooe=0\n2015-02-01 16:39:30.053+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db hit=0 miss=2 switches=0 ooe=0\n2015-02-01 16:39:30.054+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db.names hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:30.055+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:30.055+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.strings hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:30.056+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index.keys hit=0 miss=6 switches=0 ooe=0\n2015-02-01 16:39:30.057+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index hit=0 miss=6 switches=0 ooe=0\n2015-02-01 16:39:30.057+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.arrays hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:30.058+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db hit=20 miss=0 switches=0 ooe=0\n2015-02-01 16:39:30.059+0000 INFO  [org.neo4j]: marathon/neostore.relationshipstore.db hit=10 miss=0 switches=0 ooe=0\n2015-02-01 16:39:30.059+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db.labels hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:30.060+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db hit=10 miss=0 switches=0 ooe=0\n2015-02-01 16:39:30.061+0000 INFO  [org.neo4j]: marathon/neostore.schemastore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:30.061+0000 INFO  [org.neo4j]: marathon/neostore.relationshipgroupstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-01 16:39:30.062+0000 INFO  [org.neo4j]: marathon/neostore hit=0 miss=26 switches=0 ooe=0\n2015-02-01 16:39:30.063+0000 INFO  [org.neo4j]: NeoStore closed\n2015-02-01 16:39:30.063+0000 INFO  [org.neo4j]: --- STOPPING diagnostics START ---\n2015-02-01 16:39:30.063+0000 INFO  [org.neo4j]: --- STOPPING diagnostics END ---\n2015-02-02 01:28:48.120+0000 INFO  [org.neo4j]: No locking implementation specified, defaulting to 'community'\n2015-02-02 01:28:48.199+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics START ---\n2015-02-02 01:28:48.201+0000 INFO  [org.neo4j]: Neo4j Kernel properties:\n    neostore.propertystore.db.mapped_memory=1326M\n    neostore.nodestore.db.mapped_memory=368M\n    neostore.relationshipstore.db.mapped_memory=1624M\n    neostore.propertystore.db.strings.mapped_memory=1127M\n    store_dir=marathon\n    neostore.propertystore.db.arrays.mapped_memory=1277M\n    ephemeral=false\n2015-02-02 01:28:48.203+0000 INFO  [org.neo4j]: Diagnostics providers:\n    org.neo4j.kernel.configuration.Config\n    org.neo4j.kernel.info.DiagnosticsManager\n    SYSTEM_MEMORY\n    JAVA_MEMORY\n    OPERATING_SYSTEM\n    JAVA_VIRTUAL_MACHINE\n    CLASSPATH\n    LIBRARY_PATH\n    SYSTEM_PROPERTIES\n    NETWORK\n2015-02-02 01:28:48.206+0000 INFO  [org.neo4j]: System memory information:\n    Total Physical memory: 16.00 GB\n    Free Physical memory: 2.49 GB\n    Committed virtual memory: 6.81 GB\n    Total swap space: 1.00 GB\n    Free swap space: 981.75 MB\n2015-02-02 01:28:48.211+0000 INFO  [org.neo4j]: JVM memory information:\n    Free  memory: 262.02 MB\n    Total memory: 310.00 MB\n    Max   memory: 3.56 GB\n    Garbage Collector: PS Scavenge: [PS Eden Space, PS Survivor Space]\n    Garbage Collector: PS MarkSweep: [PS Eden Space, PS Survivor Space, PS Old Gen, PS Perm Gen]\n    Memory Pool: Code Cache (Non-heap memory): committed=3.19 MB, used=3.01 MB, max=48.00 MB, threshold=0.00 B\n    Memory Pool: PS Eden Space (Heap memory): committed=129.00 MB, used=25.29 MB, max=1.31 GB, threshold=?\n    Memory Pool: PS Survivor Space (Heap memory): committed=10.50 MB, used=10.49 MB, max=10.50 MB, threshold=?\n    Memory Pool: PS Old Gen (Heap memory): committed=170.50 MB, used=12.19 MB, max=2.67 GB, threshold=0.00 B\n    Memory Pool: PS Perm Gen (Non-heap memory): committed=25.50 MB, used=25.15 MB, max=82.00 MB, threshold=0.00 B\n2015-02-02 01:28:48.219+0000 INFO  [org.neo4j]: Operating system information:\n    Operating System: Mac OS X; version: 10.10.2; arch: x86_64; cpus: 8\n    Max number of file descriptors: 10240\n    Number of open file descriptors: 71\n    Process id: 5798@Dierk-Konigs-MacBook-Pro.local\n    Byte order: LITTLE_ENDIAN\n    Local timezone: Europe/Zurich\n2015-02-02 01:28:48.221+0000 INFO  [org.neo4j]: JVM information:\n    VM Name: Java HotSpot(TM) 64-Bit Server VM\n    VM Vendor: Oracle Corporation\n    VM Version: 24.51-b03\n    JIT compiler: HotSpot 64-Bit Tiered Compilers\n    VM Arguments: [-Dscript.name=/Users/dierkkoenig/.gvm/groovy/2.4.0/bin/groovy, -Dprogram.name=groovy, -Dgroovy.starter.conf=/Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf, -Dgroovy.home=/Users/dierkkoenig/.gvm/groovy/2.4.0, -Dtools.jar=/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar]\n2015-02-02 01:28:48.222+0000 INFO  [org.neo4j]: Java classpath:\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/qdox-1.12.1.jar\n     [loader.3] file:/System/Library/Java/Extensions/dns_sd.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jcommander-1.47.jar\n     [loader.2] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-1.9.4.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jce.jar\n     [loader.3] file:/Users/dierkkoenig/Library/Java/Extensions/libJNPRAuthKit.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/bsf-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/MRJToolkit.jar\n     [loader.3] file:/opt/subversion/lib/libsvnjavahl-1.0.0.0.dylib\n     [loader.3] file:/System/Library/Java/Extensions/vecmath.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/sunrsasign.jar\n     [loader.3] file:/System/Library/Java/Extensions/libmlib_jai.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-groovysh-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-antlr-1.9.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/xmlpull-1.1.3.1.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-bsf-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-nio-2.4.0.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunec.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/servlet-api-2.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-sql-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-xml-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3D.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jsp-api-2.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/mlibwrapper_jai.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-primitive-collections/jars/neo4j-primitive-collections-2.1.6.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.lucene/lucene-core/jars/lucene-core-3.6.2.jar\n     [loader.3] file:/Library/Java/Extensions/librxtxSerial.jnilib\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/localedata.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/charsets.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-ant-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-test-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DAudio.jnilib\n     [loader.3] file:/System/Library/Java/Extensions/libAppleScriptEngine.jnilib\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jfr.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3daudio.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-groovydoc-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-jmx-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DUtils.jnilib\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-kernel/jars/neo4j-kernel-2.1.6.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dcore.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jansi-1.11.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/openbeans-1.0.jar\n     [loader.3] file:/usr/lib/java/libjdns_sd.jnilib\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-junit-1.9.4.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jsse.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jline-2.12.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/zipfs.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dutils.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/classes\n     [loader.3] file:/System/Library/Java/Extensions/jai_core.jar\n     [loader.1] file:/projects/git/regina/listings/chap13/./\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ivy-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-lucene-index/jars/neo4j-lucene-index-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-json-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.groovy/grapes/org.hsqldb/hsqldb/jars/hsqldb-2.3.2.jar\n     [loader.3] file:/System/Library/Java/Extensions/jai_codec.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-console-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-templates-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jsr166y-1.7.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-swing-2.4.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/resources.jar\n     [loader.3] file:/Library/Java/Extensions/RXTXcomm.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/hamcrest-core-1.3.jar\n     [loader.1] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-launcher-1.9.4.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.geronimo.specs/geronimo-jta_1.1_spec/jars/geronimo-jta_1.1_spec-1.1.1.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/dnsns.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-docgenerator-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/multiverse-core-0.7.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/commons-logging-1.2.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/rt.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/xstream-1.4.7.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/commons-cli-1.2.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-jsr223-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/junit-4.12.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-testng-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-servlet-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/AppleScriptEngine.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/testng-6.8.13.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/gpars-1.2.1.jar\n2015-02-02 01:28:48.226+0000 INFO  [org.neo4j]: Library path:\n    /Users/dierkkoenig/Library/Java/Extensions\n    /Library/Java/Extensions\n    /Network/Library/Java/Extensions\n    /System/Library/Java/Extensions\n    /usr/lib/java\n    /projects/git/regina/listings/chap13\n2015-02-02 01:28:48.226+0000 INFO  [org.neo4j]: System.properties:\n    sun.boot.library.path = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib\n    user.country.format = CH\n    gopherProxySet = false\n    path.separator = :\n    file.encoding.pkg = sun.io\n    user.country = DE\n    sun.java.launcher = SUN_STANDARD\n    sun.os.patch.level = unknown\n    program.name = groovy\n    user.dir = /projects/git/regina/listings/chap13\n    tools.jar = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n    sun.jnu.encoding = UTF-8\n    script.name = /Users/dierkkoenig/.gvm/groovy/2.4.0/bin/groovy\n    sun.management.compiler = HotSpot 64-Bit Tiered Compilers\n    http.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    user.home = /Users/dierkkoenig\n    user.timezone = Europe/Zurich\n    file.encoding = UTF-8\n    user.name = dierkkoenig\n    sun.java.command = org.codehaus.groovy.tools.GroovyStarter --main groovy.ui.GroovyMain --conf /Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf --classpath . ../../test\n    sun.arch.data.model = 64\n    user.language = de\n    awt.toolkit = sun.lwawt.macosx.LWCToolkit\n    file.separator = /\n    sun.io.unicode.encoding = UnicodeBig\n    sun.cpu.endian = little\n    groovy.starter.conf = /Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf\n    socksNonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    ftp.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    groovy.home = /Users/dierkkoenig/.gvm/groovy/2.4.0\n    sun.cpu.isalist = \n2015-02-02 01:28:48.227+0000 INFO  [org.neo4j]: Network information:\n    Interface awdl0:\n        address: fe80:0:0:0:b49d:fbff:fe48:bef5%10\n    Interface en0:\n        address: fe80:0:0:0:2acf:e9ff:fe19:ca6d%5\n        address: 10.0.1.19\n    Interface lo0:\n        address: fe80:0:0:0:0:0:0:1%1\n        address: 0:0:0:0:0:0:0:1\n        address: 127.0.0.1\n2015-02-02 01:28:48.230+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics END ---\n2015-02-02 01:28:48.297+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=114b)\n2015-02-02 01:28:48.299+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=10b)\n2015-02-02 01:28:48.301+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-02-02 01:28:48.304+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-02-02 01:28:48.306+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.strings] brickCount=0 brickSize=1181696b mappedMem=1181745152b (storeSize=128b)\n2015-02-02 01:28:48.308+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index.keys] brickCount=0 brickSize=0b mappedMem=0b (storeSize=266b)\n2015-02-02 01:28:48.310+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index] brickCount=0 brickSize=0b mappedMem=0b (storeSize=54b)\n2015-02-02 01:28:48.313+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.arrays] brickCount=0 brickSize=1339008b mappedMem=1339031552b (storeSize=128b)\n2015-02-02 01:28:48.329+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db] brickCount=0 brickSize=1390392b mappedMem=1390411776b (storeSize=820b)\n2015-02-02 01:28:48.334+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipstore.db] brickCount=0 brickSize=1702856b mappedMem=1702887424b (storeSize=340b)\n2015-02-02 01:28:48.336+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db.labels] brickCount=0 brickSize=0b mappedMem=0b (storeSize=68b)\n2015-02-02 01:28:48.340+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db] brickCount=0 brickSize=385875b mappedMem=385875968b (storeSize=150b)\n2015-02-02 01:28:48.343+0000 INFO  [org.neo4j]: [marathon/neostore.schemastore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=64b)\n2015-02-02 01:28:48.346+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipgroupstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=25b)\n2015-02-02 01:28:48.348+0000 INFO  [org.neo4j]: [marathon/neostore] brickCount=0 brickSize=0b mappedMem=0b (storeSize=81b)\n2015-02-02 01:28:48.586+0000 INFO  [org.neo4j]: Opened logical log [marathon/nioneo_logical.log.1] version=1, lastTxId=10 (clean)\n2015-02-02 01:28:48.592+0000 INFO  [org.neo4j]: TM opening log: marathon/tm_tx_log.1\n2015-02-02 01:28:48.600+0000 INFO  [org.neo4j]: Kernel health set to OK\n2015-02-02 01:28:48.612+0000 INFO  [org.neo4j]: Opened logical log [marathon/index/lucene.log.1] version=1, lastTxId=1 (clean)\n2015-02-02 01:28:48.618+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions START ---\n2015-02-02 01:28:48.618+0000 INFO  [org.neo4j]: Graph Database: org.neo4j.kernel.EmbeddedGraphDatabase StoreId{creationTime=1422808769411, randomId=1762119504651947014, storeVersion=14406081294923270, upgradeTime=1422808769411, upgradeId=1762119504651947014}\n2015-02-02 01:28:48.620+0000 INFO  [org.neo4j]: Kernel version: Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6\n2015-02-02 01:28:48.620+0000 INFO  [org.neo4j]: Neo4j component versions:\n2015-02-02 01:28:48.621+0000 INFO  [org.neo4j]:   Neo4j - Lucene Index (neo4j-lucene-index), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-02 01:28:48.621+0000 INFO  [org.neo4j]:   Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-02 01:28:48.621+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions END ---\n2015-02-02 01:28:48.624+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS START ---\n2015-02-02 01:28:48.625+0000 INFO  [org.neo4j]: Store versions:\n    Store versions:\n      NeoStore v0.A.3\n      SchemaStore v0.A.3\n      NodeStore v0.A.3\n      RelationshipStore v0.A.3\n      RelationshipTypeStore v0.A.3\n      LabelTokenStore v0.A.3\n      PropertyStore v0.A.3\n      PropertyIndexStore v0.A.3\n      StringPropertyStore v0.A.3\n      ArrayPropertyStore v0.A.3\n      RelationshipGroupStore v0.A.3\n2015-02-02 01:28:48.625+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS END ---\n2015-02-02 01:28:48.625+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE START ---\n2015-02-02 01:28:48.625+0000 INFO  [org.neo4j]: Id usage:\n    Id usage:\n      SchemaStore: used=1 high=0\n      NodeStore: used=10 high=9\n      RelationshipStore: used=10 high=9\n      RelationshipTypeStore: used=2 high=1\n      LabelTokenStore: used=0 high=-1\n      PropertyStore: used=20 high=19\n      PropertyIndexStore: used=6 high=5\n      StringPropertyStore: used=1 high=0\n      ArrayPropertyStore: used=1 high=0\n      RelationshipGroupStore: used=1 high=0\n2015-02-02 01:28:48.626+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE END ---\n2015-02-02 01:28:48.626+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS START ---\n2015-02-02 01:28:48.626+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS END ---\n2015-02-02 01:28:48.627+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles START ---\n2015-02-02 01:28:48.627+0000 INFO  [org.neo4j]: Disk space on partition (Total / Free / Free %): 499082485760 / 174778966016 / 35\nStorage files: (filename : modification date - size)\n      active_tx_log: 2015-02-01T17:39:29+0100 - 11.00 B\n      index:\n        lucene-store.db: 2015-02-01T17:39:30+0100 - 40.00 B\n        lucene.log.1: 2015-02-02T02:28:48+0100 - 16.00 B\n        lucene.log.active: 2015-02-02T02:28:48+0100 - 4.00 B\n        lucene.log.v0: 2015-02-01T17:39:30+0100 - 16.00 B\n      - Total: 2015-02-02T02:28:48+0100 - 76.00 B\n      lock: 2015-02-02T02:28:48+0100 - 0.00 B\n      messages.log: 2015-02-02T02:28:48+0100 - 45.09 kB\n      neostore: 2015-02-02T02:28:48+0100 - 81.00 B\n      neostore.id: 2015-02-02T02:28:48+0100 - 9.00 B\n      neostore.labeltokenstore.db: 2015-02-02T02:28:48+0100 - 0.00 B\n      neostore.labeltokenstore.db.id: 2015-02-02T02:28:48+0100 - 9.00 B\n      neostore.labeltokenstore.db.names: 2015-02-02T02:28:48+0100 - 38.00 B\n      neostore.labeltokenstore.db.names.id: 2015-02-02T02:28:48+0100 - 9.00 B\n      neostore.nodestore.db: 2015-02-02T02:28:48+0100 - 150.00 B\n      neostore.nodestore.db.id: 2015-02-02T02:28:48+0100 - 9.00 B\n      neostore.nodestore.db.labels: 2015-02-02T02:28:48+0100 - 68.00 B\n      neostore.nodestore.db.labels.id: 2015-02-02T02:28:48+0100 - 9.00 B\n      neostore.propertystore.db: 2015-02-02T02:28:48+0100 - 820.00 B\n      neostore.propertystore.db.arrays: 2015-02-02T02:28:48+0100 - 128.00 B\n      neostore.propertystore.db.arrays.id: 2015-02-02T02:28:48+0100 - 9.00 B\n      neostore.propertystore.db.id: 2015-02-02T02:28:48+0100 - 9.00 B\n      neostore.propertystore.db.index: 2015-02-02T02:28:48+0100 - 54.00 B\n      neostore.propertystore.db.index.id: 2015-02-02T02:28:48+0100 - 9.00 B\n      neostore.propertystore.db.index.keys: 2015-02-02T02:28:48+0100 - 266.00 B\n      neostore.propertystore.db.index.keys.id: 2015-02-02T02:28:48+0100 - 9.00 B\n      neostore.propertystore.db.strings: 2015-02-02T02:28:48+0100 - 128.00 B\n      neostore.propertystore.db.strings.id: 2015-02-02T02:28:48+0100 - 9.00 B\n      neostore.relationshipgroupstore.db: 2015-02-02T02:28:48+0100 - 25.00 B\n      neostore.relationshipgroupstore.db.id: 2015-02-02T02:28:48+0100 - 9.00 B\n      neostore.relationshipstore.db: 2015-02-02T02:28:48+0100 - 340.00 B\n      neostore.relationshipstore.db.id: 2015-02-02T02:28:48+0100 - 9.00 B\n      neostore.relationshiptypestore.db: 2015-02-02T02:28:48+0100 - 10.00 B\n      neostore.relationshiptypestore.db.id: 2015-02-02T02:28:48+0100 - 9.00 B\n      neostore.relationshiptypestore.db.names: 2015-02-02T02:28:48+0100 - 114.00 B\n      neostore.relationshiptypestore.db.names.id: 2015-02-02T02:28:48+0100 - 9.00 B\n      neostore.schemastore.db: 2015-02-02T02:28:48+0100 - 64.00 B\n      neostore.schemastore.db.id: 2015-02-02T02:28:48+0100 - 9.00 B\n      nioneo_logical.log.1: 2015-02-02T02:28:48+0100 - 16.00 B\n      nioneo_logical.log.active: 2015-02-02T02:28:48+0100 - 4.00 B\n      nioneo_logical.log.v0: 2015-02-01T17:39:30+0100 - 4.52 kB\n      schema:\n        label:\n          lucene:\n            segments.gen: 2015-02-01T17:39:30+0100 - 20.00 B\n            segments_1: 2015-02-01T17:39:30+0100 - 32.00 B\n            write.lock: 2015-02-02T02:28:48+0100 - 0.00 B\n          - Total: 2015-02-02T02:28:48+0100 - 52.00 B\n        - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      store_lock: 2015-02-01T17:39:29+0100 - 0.00 B\n      tm_tx_log.1: 2015-02-02T02:28:48+0100 - 0.00 B\n2015-02-02 01:28:48.637+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles END ---\n2015-02-02 01:28:48.685+0000 INFO  [org.neo4j]: Database is now ready\n2015-02-02 01:28:48.914+0000 INFO  [org.neo4j]: Shutdown started\n2015-02-02 01:28:48.914+0000 INFO  [org.neo4j]: Database is now unavailable\n2015-02-02 01:28:48.918+0000 INFO  [org.neo4j]: Closed log marathon/index/lucene.log\n2015-02-02 01:28:48.918+0000 INFO  [org.neo4j]: TM shutting down\n2015-02-02 01:28:48.924+0000 INFO  [org.neo4j]: Closed log marathon/nioneo_logical.log\n2015-02-02 01:28:48.925+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db.names hit=0 miss=4 switches=0 ooe=0\n2015-02-02 01:28:48.926+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db hit=0 miss=2 switches=0 ooe=0\n2015-02-02 01:28:48.927+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db.names hit=0 miss=0 switches=0 ooe=0\n2015-02-02 01:28:48.928+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-02 01:28:48.929+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.strings hit=0 miss=0 switches=0 ooe=0\n2015-02-02 01:28:48.929+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index.keys hit=0 miss=12 switches=0 ooe=0\n2015-02-02 01:28:48.930+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index hit=0 miss=6 switches=0 ooe=0\n2015-02-02 01:28:48.930+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.arrays hit=0 miss=0 switches=0 ooe=0\n2015-02-02 01:28:48.931+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db hit=20 miss=0 switches=0 ooe=0\n2015-02-02 01:28:48.932+0000 INFO  [org.neo4j]: marathon/neostore.relationshipstore.db hit=10 miss=0 switches=0 ooe=0\n2015-02-02 01:28:48.933+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db.labels hit=0 miss=0 switches=0 ooe=0\n2015-02-02 01:28:48.934+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db hit=10 miss=0 switches=0 ooe=0\n2015-02-02 01:28:48.934+0000 INFO  [org.neo4j]: marathon/neostore.schemastore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-02 01:28:48.935+0000 INFO  [org.neo4j]: marathon/neostore.relationshipgroupstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-02 01:28:48.937+0000 INFO  [org.neo4j]: marathon/neostore hit=0 miss=18 switches=0 ooe=0\n2015-02-02 01:28:48.938+0000 INFO  [org.neo4j]: NeoStore closed\n2015-02-02 01:28:48.938+0000 INFO  [org.neo4j]: --- STOPPING diagnostics START ---\n2015-02-02 01:28:48.938+0000 INFO  [org.neo4j]: --- STOPPING diagnostics END ---\n2015-02-02 01:29:25.276+0000 INFO  [org.neo4j]: No locking implementation specified, defaulting to 'community'\n2015-02-02 01:29:25.340+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics START ---\n2015-02-02 01:29:25.342+0000 INFO  [org.neo4j]: Neo4j Kernel properties:\n    neostore.propertystore.db.mapped_memory=1326M\n    neostore.nodestore.db.mapped_memory=368M\n    neostore.relationshipstore.db.mapped_memory=1624M\n    neostore.propertystore.db.strings.mapped_memory=1127M\n    store_dir=marathon\n    neostore.propertystore.db.arrays.mapped_memory=1277M\n    ephemeral=false\n2015-02-02 01:29:25.343+0000 INFO  [org.neo4j]: Diagnostics providers:\n    org.neo4j.kernel.configuration.Config\n    org.neo4j.kernel.info.DiagnosticsManager\n    SYSTEM_MEMORY\n    JAVA_MEMORY\n    OPERATING_SYSTEM\n    JAVA_VIRTUAL_MACHINE\n    CLASSPATH\n    LIBRARY_PATH\n    SYSTEM_PROPERTIES\n    NETWORK\n2015-02-02 01:29:25.344+0000 INFO  [org.neo4j]: System memory information:\n    Total Physical memory: 16.00 GB\n    Free Physical memory: 2.38 GB\n    Committed virtual memory: 6.80 GB\n    Total swap space: 1.00 GB\n    Free swap space: 981.75 MB\n2015-02-02 01:29:25.345+0000 INFO  [org.neo4j]: JVM memory information:\n    Free  memory: 253.70 MB\n    Total memory: 310.50 MB\n    Max   memory: 3.56 GB\n    Garbage Collector: PS Scavenge: [PS Eden Space, PS Survivor Space]\n    Garbage Collector: PS MarkSweep: [PS Eden Space, PS Survivor Space, PS Old Gen, PS Perm Gen]\n    Memory Pool: Code Cache (Non-heap memory): committed=4.06 MB, used=3.98 MB, max=48.00 MB, threshold=0.00 B\n    Memory Pool: PS Eden Space (Heap memory): committed=125.00 MB, used=18.93 MB, max=1.30 GB, threshold=?\n    Memory Pool: PS Survivor Space (Heap memory): committed=15.00 MB, used=14.69 MB, max=15.00 MB, threshold=?\n    Memory Pool: PS Old Gen (Heap memory): committed=170.50 MB, used=23.18 MB, max=2.67 GB, threshold=0.00 B\n    Memory Pool: PS Perm Gen (Non-heap memory): committed=36.50 MB, used=36.35 MB, max=82.00 MB, threshold=0.00 B\n2015-02-02 01:29:25.347+0000 INFO  [org.neo4j]: Operating system information:\n    Operating System: Mac OS X; version: 10.10.2; arch: x86_64; cpus: 8\n    Max number of file descriptors: 10240\n    Number of open file descriptors: 101\n    Process id: 5798@Dierk-Konigs-MacBook-Pro.local\n    Byte order: LITTLE_ENDIAN\n    Local timezone: Europe/Zurich\n2015-02-02 01:29:25.348+0000 INFO  [org.neo4j]: JVM information:\n    VM Name: Java HotSpot(TM) 64-Bit Server VM\n    VM Vendor: Oracle Corporation\n    VM Version: 24.51-b03\n    JIT compiler: HotSpot 64-Bit Tiered Compilers\n    VM Arguments: [-Dscript.name=/Users/dierkkoenig/.gvm/groovy/2.4.0/bin/groovy, -Dprogram.name=groovy, -Dgroovy.starter.conf=/Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf, -Dgroovy.home=/Users/dierkkoenig/.gvm/groovy/2.4.0, -Dtools.jar=/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar]\n2015-02-02 01:29:25.349+0000 INFO  [org.neo4j]: Java classpath:\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/qdox-1.12.1.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.parboiled/parboiled-scala_2.10/jars/parboiled-scala_2.10-1.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jcommander-1.47.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/bsf-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-configuration/commons-configuration/jars/commons-configuration-1.6.jar\n     [loader.3] file:/Users/dierkkoenig/Library/Java/Extensions/libJNPRAuthKit.jnilib\n     [loader.3] file:/System/Library/Java/Extensions/vecmath.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-groovysh-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-logging/commons-logging/jars/commons-logging-1.1.1.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-antlr-1.9.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/xmlpull-1.1.3.1.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunec.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3D.jnilib\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-lang/commons-lang/jars/commons-lang-2.4.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/localedata.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/charsets.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3daudio.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dcore.jar\n     [loader.3] file:/usr/lib/java/libjdns_sd.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-junit-1.9.4.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-management/jars/neo4j-management-2.1.6.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/zipfs.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.gremlin/gremlin-groovy/jars/gremlin-groovy-2.6.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/classes\n     [loader.3] file:/System/Library/Java/Extensions/jai_core.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ivy-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-json-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-templates-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.gremlin/gremlin-java/jars/gremlin-java-2.6.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/hamcrest-core-1.3.jar\n     [loader.3] file:/Library/Java/Extensions/RXTXcomm.jar\n     [loader.1] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.geronimo.specs/geronimo-jta_1.1_spec/jars/geronimo-jta_1.1_spec-1.1.1.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/dnsns.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/multiverse-core-0.7.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-commons/jars/neo4j-cypher-commons-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/junit-4.12.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-servlet-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/AppleScriptEngine.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/testng-6.8.13.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.parboiled/parboiled-core/jars/parboiled-core-1.1.6.jar\n     [loader.3] file:/System/Library/Java/Extensions/dns_sd.jar\n     [loader.2] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-1.9.4.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jce.jar\n     [loader.3] file:/System/Library/Java/Extensions/MRJToolkit.jar\n     [loader.3] file:/opt/subversion/lib/libsvnjavahl-1.0.0.0.dylib\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-beanutils/commons-beanutils/jars/commons-beanutils-1.7.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/sunrsasign.jar\n     [loader.3] file:/System/Library/Java/Extensions/libmlib_jai.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-bsf-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-nio-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/servlet-api-2.4.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-digester/commons-digester/jars/commons-digester-1.8.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-sql-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-xml-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jsp-api-2.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-compiler-2.0/jars/neo4j-cypher-compiler-2.0-2.0.4.jar\n     [loader.3] file:/System/Library/Java/Extensions/mlibwrapper_jai.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-primitive-collections/jars/neo4j-primitive-collections-2.1.6.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.lucene/lucene-core/jars/lucene-core-3.6.2.jar\n     [loader.3] file:/Library/Java/Extensions/librxtxSerial.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-ant-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher/jars/neo4j-cypher-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-test-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DAudio.jnilib\n     [loader.3] file:/System/Library/Java/Extensions/libAppleScriptEngine.jnilib\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jfr.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.scala-lang/scala-library/jars/scala-library-2.10.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-groovydoc-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-jmx-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DUtils.jnilib\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-kernel/jars/neo4j-kernel-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jansi-1.11.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/openbeans-1.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jsse.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jline-2.12.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dutils.jar\n     [loader.1] file:/projects/git/regina/listings/chap13/./\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-lucene-index/jars/neo4j-lucene-index-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.groovy/grapes/org.hsqldb/hsqldb/jars/hsqldb-2.3.2.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar\n     [loader.3] file:/System/Library/Java/Extensions/jai_codec.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-beanutils/commons-beanutils-core/jars/commons-beanutils-core-1.8.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-console-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.blueprints/blueprints-neo4j2-graph/jars/blueprints-neo4j2-graph-2.6.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jsr166y-1.7.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.blueprints/blueprints-core/jars/blueprints-core-2.6.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-swing-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-compiler-2.1/jars/neo4j-cypher-compiler-2.1-2.1.6.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/resources.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-launcher-1.9.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-docgenerator-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/commons-logging-1.2.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/rt.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/xstream-1.4.7.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/commons-cli-1.2.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-jsr223-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-testng-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-collections/commons-collections/jars/commons-collections-3.2.1.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop/pipes/jars/pipes-2.6.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.googlecode.concurrentlinkedhashmap/concurrentlinkedhashmap-lru/jars/concurrentlinkedhashmap-lru-1.4.1.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/gpars-1.2.1.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-compiler-1.9/jars/neo4j-cypher-compiler-1.9-2.0.4.jar\n2015-02-02 01:29:25.353+0000 INFO  [org.neo4j]: Library path:\n    /Users/dierkkoenig/Library/Java/Extensions\n    /Library/Java/Extensions\n    /Network/Library/Java/Extensions\n    /System/Library/Java/Extensions\n    /usr/lib/java\n    /projects/git/regina/listings/chap13\n2015-02-02 01:29:25.353+0000 INFO  [org.neo4j]: System.properties:\n    sun.boot.library.path = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib\n    user.country.format = CH\n    gopherProxySet = false\n    path.separator = :\n    file.encoding.pkg = sun.io\n    user.country = DE\n    sun.java.launcher = SUN_STANDARD\n    sun.os.patch.level = unknown\n    program.name = groovy\n    user.dir = /projects/git/regina/listings/chap13\n    tools.jar = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n    sun.jnu.encoding = UTF-8\n    script.name = /Users/dierkkoenig/.gvm/groovy/2.4.0/bin/groovy\n    sun.management.compiler = HotSpot 64-Bit Tiered Compilers\n    http.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    user.home = /Users/dierkkoenig\n    user.timezone = Europe/Zurich\n    file.encoding = UTF-8\n    user.name = dierkkoenig\n    sun.java.command = org.codehaus.groovy.tools.GroovyStarter --main groovy.ui.GroovyMain --conf /Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf --classpath . ../../test\n    sun.arch.data.model = 64\n    user.language = de\n    awt.toolkit = sun.lwawt.macosx.LWCToolkit\n    file.separator = /\n    sun.io.unicode.encoding = UnicodeBig\n    sun.cpu.endian = little\n    groovy.starter.conf = /Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf\n    socksNonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    ftp.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    groovy.home = /Users/dierkkoenig/.gvm/groovy/2.4.0\n    sun.cpu.isalist = \n2015-02-02 01:29:25.353+0000 INFO  [org.neo4j]: Network information:\n    Interface awdl0:\n        address: fe80:0:0:0:b49d:fbff:fe48:bef5%10\n    Interface en0:\n        address: fe80:0:0:0:2acf:e9ff:fe19:ca6d%5\n        address: 10.0.1.19\n    Interface lo0:\n        address: fe80:0:0:0:0:0:0:1%1\n        address: 0:0:0:0:0:0:0:1\n        address: 127.0.0.1\n2015-02-02 01:29:25.354+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics END ---\n2015-02-02 01:29:25.397+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=114b)\n2015-02-02 01:29:25.399+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=10b)\n2015-02-02 01:29:25.399+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-02-02 01:29:25.400+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-02-02 01:29:25.400+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.strings] brickCount=0 brickSize=1181696b mappedMem=1181745152b (storeSize=128b)\n2015-02-02 01:29:25.400+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index.keys] brickCount=0 brickSize=0b mappedMem=0b (storeSize=266b)\n2015-02-02 01:29:25.401+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index] brickCount=0 brickSize=0b mappedMem=0b (storeSize=54b)\n2015-02-02 01:29:25.402+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.arrays] brickCount=0 brickSize=1339008b mappedMem=1339031552b (storeSize=128b)\n2015-02-02 01:29:25.414+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db] brickCount=0 brickSize=1390392b mappedMem=1390411776b (storeSize=1640b)\n2015-02-02 01:29:25.416+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipstore.db] brickCount=0 brickSize=1702856b mappedMem=1702887424b (storeSize=680b)\n2015-02-02 01:29:25.416+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db.labels] brickCount=0 brickSize=0b mappedMem=0b (storeSize=68b)\n2015-02-02 01:29:25.418+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db] brickCount=0 brickSize=385875b mappedMem=385875968b (storeSize=300b)\n2015-02-02 01:29:25.419+0000 INFO  [org.neo4j]: [marathon/neostore.schemastore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=64b)\n2015-02-02 01:29:25.420+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipgroupstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=25b)\n2015-02-02 01:29:25.421+0000 INFO  [org.neo4j]: [marathon/neostore] brickCount=0 brickSize=0b mappedMem=0b (storeSize=81b)\n2015-02-02 01:29:25.559+0000 INFO  [org.neo4j]: Opened logical log [marathon/nioneo_logical.log.1] version=2, lastTxId=11 (clean)\n2015-02-02 01:29:25.567+0000 INFO  [org.neo4j]: TM opening log: marathon/tm_tx_log.1\n2015-02-02 01:29:25.574+0000 INFO  [org.neo4j]: Kernel health set to OK\n2015-02-02 01:29:25.582+0000 INFO  [org.neo4j]: Opened logical log [marathon/index/lucene.log.1] version=2, lastTxId=1 (clean)\n2015-02-02 01:29:25.586+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions START ---\n2015-02-02 01:29:25.586+0000 INFO  [org.neo4j]: Graph Database: org.neo4j.kernel.EmbeddedGraphDatabase StoreId{creationTime=1422808769411, randomId=1762119504651947014, storeVersion=14406081294923270, upgradeTime=1422808769411, upgradeId=1762119504651947014}\n2015-02-02 01:29:25.595+0000 INFO  [org.neo4j]: Kernel version: Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6\n2015-02-02 01:29:25.595+0000 INFO  [org.neo4j]: Neo4j component versions:\n2015-02-02 01:29:25.597+0000 INFO  [org.neo4j]:   Neo4j - Lucene Index (neo4j-lucene-index), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-02 01:29:25.597+0000 INFO  [org.neo4j]:   Neo4j - Cypher Compiler 2.1 (neo4j-cypher-compiler-2.1), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-02 01:29:25.597+0000 INFO  [org.neo4j]:   Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-02 01:29:25.597+0000 INFO  [org.neo4j]:   Neo4j - Cypher (neo4j-cypher), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-02 01:29:25.597+0000 INFO  [org.neo4j]:   Neo4j - Graph DB Monitoring and Management tools (neo4j-management), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-02 01:29:25.598+0000 INFO  [org.neo4j]:   Neo4j - Cypher Compiler 2.0 (neo4j-cypher-compiler-2.0), version: 2.0.4; revision: 2.0.4:2.0-maint:130/4a7d10bc274a5d26a180bbe9df25100e8a694748\n2015-02-02 01:29:25.598+0000 INFO  [org.neo4j]:   Neo4j - Cypher Compiler 1.9 (neo4j-cypher-compiler-1.9), version: 2.0.4; revision: 2.0.4:2.0-maint:130/4a7d10bc274a5d26a180bbe9df25100e8a694748\n2015-02-02 01:29:25.598+0000 INFO  [org.neo4j]:   Neo4j - Cypher Commons (neo4j-cypher-commons), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-02 01:29:25.598+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions END ---\n2015-02-02 01:29:25.600+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS START ---\n2015-02-02 01:29:25.600+0000 INFO  [org.neo4j]: Store versions:\n    Store versions:\n      NeoStore v0.A.3\n      SchemaStore v0.A.3\n      NodeStore v0.A.3\n      RelationshipStore v0.A.3\n      RelationshipTypeStore v0.A.3\n      LabelTokenStore v0.A.3\n      PropertyStore v0.A.3\n      PropertyIndexStore v0.A.3\n      StringPropertyStore v0.A.3\n      ArrayPropertyStore v0.A.3\n      RelationshipGroupStore v0.A.3\n2015-02-02 01:29:25.600+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS END ---\n2015-02-02 01:29:25.600+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE START ---\n2015-02-02 01:29:25.600+0000 INFO  [org.neo4j]: Id usage:\n    Id usage:\n      SchemaStore: used=1 high=0\n      NodeStore: used=20 high=19\n      RelationshipStore: used=20 high=19\n      RelationshipTypeStore: used=2 high=1\n      LabelTokenStore: used=0 high=-1\n      PropertyStore: used=40 high=39\n      PropertyIndexStore: used=6 high=5\n      StringPropertyStore: used=1 high=0\n      ArrayPropertyStore: used=1 high=0\n      RelationshipGroupStore: used=1 high=0\n2015-02-02 01:29:25.601+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE END ---\n2015-02-02 01:29:25.601+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS START ---\n2015-02-02 01:29:25.601+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS END ---\n2015-02-02 01:29:25.601+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles START ---\n2015-02-02 01:29:25.602+0000 INFO  [org.neo4j]: Disk space on partition (Total / Free / Free %): 499082485760 / 174755573760 / 35\nStorage files: (filename : modification date - size)\n      active_tx_log: 2015-02-01T17:39:29+0100 - 11.00 B\n      index:\n        lucene-store.db: 2015-02-02T02:28:48+0100 - 40.00 B\n        lucene.log.1: 2015-02-02T02:29:25+0100 - 16.00 B\n        lucene.log.active: 2015-02-02T02:29:25+0100 - 4.00 B\n        lucene.log.v0: 2015-02-01T17:39:30+0100 - 16.00 B\n        lucene.log.v1: 2015-02-02T02:28:48+0100 - 16.00 B\n      - Total: 2015-02-02T02:29:25+0100 - 92.00 B\n      lock: 2015-02-02T02:29:25+0100 - 0.00 B\n      messages.log: 2015-02-02T02:29:25+0100 - 71.99 kB\n      neostore: 2015-02-02T02:29:25+0100 - 81.00 B\n      neostore.id: 2015-02-02T02:29:25+0100 - 9.00 B\n      neostore.labeltokenstore.db: 2015-02-02T02:29:25+0100 - 0.00 B\n      neostore.labeltokenstore.db.id: 2015-02-02T02:29:25+0100 - 9.00 B\n      neostore.labeltokenstore.db.names: 2015-02-02T02:29:25+0100 - 38.00 B\n      neostore.labeltokenstore.db.names.id: 2015-02-02T02:29:25+0100 - 9.00 B\n      neostore.nodestore.db: 2015-02-02T02:29:25+0100 - 300.00 B\n      neostore.nodestore.db.id: 2015-02-02T02:29:25+0100 - 9.00 B\n      neostore.nodestore.db.labels: 2015-02-02T02:29:25+0100 - 68.00 B\n      neostore.nodestore.db.labels.id: 2015-02-02T02:29:25+0100 - 9.00 B\n      neostore.propertystore.db: 2015-02-02T02:29:25+0100 - 1.60 kB\n      neostore.propertystore.db.arrays: 2015-02-02T02:29:25+0100 - 128.00 B\n      neostore.propertystore.db.arrays.id: 2015-02-02T02:29:25+0100 - 9.00 B\n      neostore.propertystore.db.id: 2015-02-02T02:29:25+0100 - 9.00 B\n      neostore.propertystore.db.index: 2015-02-02T02:29:25+0100 - 54.00 B\n      neostore.propertystore.db.index.id: 2015-02-02T02:29:25+0100 - 9.00 B\n      neostore.propertystore.db.index.keys: 2015-02-02T02:29:25+0100 - 266.00 B\n      neostore.propertystore.db.index.keys.id: 2015-02-02T02:29:25+0100 - 9.00 B\n      neostore.propertystore.db.strings: 2015-02-02T02:29:25+0100 - 128.00 B\n      neostore.propertystore.db.strings.id: 2015-02-02T02:29:25+0100 - 9.00 B\n      neostore.relationshipgroupstore.db: 2015-02-02T02:29:25+0100 - 25.00 B\n      neostore.relationshipgroupstore.db.id: 2015-02-02T02:29:25+0100 - 9.00 B\n      neostore.relationshipstore.db: 2015-02-02T02:29:25+0100 - 680.00 B\n      neostore.relationshipstore.db.id: 2015-02-02T02:29:25+0100 - 9.00 B\n      neostore.relationshiptypestore.db: 2015-02-02T02:29:25+0100 - 10.00 B\n      neostore.relationshiptypestore.db.id: 2015-02-02T02:29:25+0100 - 9.00 B\n      neostore.relationshiptypestore.db.names: 2015-02-02T02:29:25+0100 - 114.00 B\n      neostore.relationshiptypestore.db.names.id: 2015-02-02T02:29:25+0100 - 9.00 B\n      neostore.schemastore.db: 2015-02-02T02:29:25+0100 - 64.00 B\n      neostore.schemastore.db.id: 2015-02-02T02:29:25+0100 - 9.00 B\n      nioneo_logical.log.1: 2015-02-02T02:29:25+0100 - 16.00 B\n      nioneo_logical.log.active: 2015-02-02T02:29:25+0100 - 4.00 B\n      nioneo_logical.log.v0: 2015-02-01T17:39:30+0100 - 4.52 kB\n      nioneo_logical.log.v1: 2015-02-02T02:28:48+0100 - 3.34 kB\n      schema:\n        label:\n          lucene:\n            segments.gen: 2015-02-01T17:39:30+0100 - 20.00 B\n            segments_1: 2015-02-01T17:39:30+0100 - 32.00 B\n            write.lock: 2015-02-02T02:29:25+0100 - 0.00 B\n          - Total: 2015-02-02T02:29:25+0100 - 52.00 B\n        - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      store_lock: 2015-02-01T17:39:29+0100 - 0.00 B\n      tm_tx_log.1: 2015-02-02T02:29:25+0100 - 0.00 B\n2015-02-02 01:29:25.609+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles END ---\n2015-02-02 01:29:25.651+0000 INFO  [org.neo4j]: Database is now ready\n2015-02-02 01:29:26.798+0000 INFO  [org.neo4j]: Shutdown started\n2015-02-02 01:29:26.800+0000 INFO  [org.neo4j]: Database is now unavailable\n2015-02-02 01:29:26.803+0000 INFO  [org.neo4j]: Closed log marathon/index/lucene.log\n2015-02-02 01:29:26.804+0000 INFO  [org.neo4j]: TM shutting down\n2015-02-02 01:29:26.809+0000 INFO  [org.neo4j]: Closed log marathon/nioneo_logical.log\n2015-02-02 01:29:26.811+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db.names hit=0 miss=4 switches=0 ooe=0\n2015-02-02 01:29:26.812+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db hit=0 miss=2 switches=0 ooe=0\n2015-02-02 01:29:26.813+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db.names hit=0 miss=0 switches=0 ooe=0\n2015-02-02 01:29:26.813+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-02 01:29:26.814+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.strings hit=0 miss=0 switches=0 ooe=0\n2015-02-02 01:29:26.815+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index.keys hit=0 miss=12 switches=0 ooe=0\n2015-02-02 01:29:26.815+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index hit=0 miss=6 switches=0 ooe=0\n2015-02-02 01:29:26.816+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.arrays hit=0 miss=0 switches=0 ooe=0\n2015-02-02 01:29:26.817+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db hit=60 miss=0 switches=0 ooe=0\n2015-02-02 01:29:26.818+0000 INFO  [org.neo4j]: marathon/neostore.relationshipstore.db hit=34 miss=0 switches=0 ooe=0\n2015-02-02 01:29:26.818+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db.labels hit=0 miss=0 switches=0 ooe=0\n2015-02-02 01:29:26.819+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db hit=60 miss=0 switches=0 ooe=0\n2015-02-02 01:29:26.820+0000 INFO  [org.neo4j]: marathon/neostore.schemastore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-02 01:29:26.821+0000 INFO  [org.neo4j]: marathon/neostore.relationshipgroupstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-02 01:29:26.823+0000 INFO  [org.neo4j]: marathon/neostore hit=0 miss=18 switches=0 ooe=0\n2015-02-02 01:29:26.824+0000 INFO  [org.neo4j]: NeoStore closed\n2015-02-02 01:29:26.824+0000 INFO  [org.neo4j]: --- STOPPING diagnostics START ---\n2015-02-02 01:29:26.824+0000 INFO  [org.neo4j]: --- STOPPING diagnostics END ---\n2015-02-06 00:41:40.694+0000 INFO  [org.neo4j]: No locking implementation specified, defaulting to 'community'\n2015-02-06 00:41:40.795+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics START ---\n2015-02-06 00:41:40.796+0000 INFO  [org.neo4j]: Neo4j Kernel properties:\n    neostore.propertystore.db.mapped_memory=1326M\n    neostore.nodestore.db.mapped_memory=368M\n    neostore.relationshipstore.db.mapped_memory=1624M\n    neostore.propertystore.db.strings.mapped_memory=1127M\n    store_dir=marathon\n    neostore.propertystore.db.arrays.mapped_memory=1277M\n    ephemeral=false\n2015-02-06 00:41:40.799+0000 INFO  [org.neo4j]: Diagnostics providers:\n    org.neo4j.kernel.configuration.Config\n    org.neo4j.kernel.info.DiagnosticsManager\n    SYSTEM_MEMORY\n    JAVA_MEMORY\n    OPERATING_SYSTEM\n    JAVA_VIRTUAL_MACHINE\n    CLASSPATH\n    LIBRARY_PATH\n    SYSTEM_PROPERTIES\n    NETWORK\n2015-02-06 00:41:40.803+0000 INFO  [org.neo4j]: System memory information:\n    Total Physical memory: 16.00 GB\n    Free Physical memory: 7.64 GB\n    Committed virtual memory: 6.81 GB\n    Total swap space: 2.00 GB\n    Free swap space: 1.19 GB\n2015-02-06 00:41:40.807+0000 INFO  [org.neo4j]: JVM memory information:\n    Free  memory: 259.47 MB\n    Total memory: 310.00 MB\n    Max   memory: 3.56 GB\n    Garbage Collector: PS Scavenge: [PS Eden Space, PS Survivor Space]\n    Garbage Collector: PS MarkSweep: [PS Eden Space, PS Survivor Space, PS Old Gen, PS Perm Gen]\n    Memory Pool: Code Cache (Non-heap memory): committed=3.19 MB, used=3.04 MB, max=48.00 MB, threshold=0.00 B\n    Memory Pool: PS Eden Space (Heap memory): committed=129.00 MB, used=27.83 MB, max=1.31 GB, threshold=?\n    Memory Pool: PS Survivor Space (Heap memory): committed=10.50 MB, used=10.48 MB, max=10.50 MB, threshold=?\n    Memory Pool: PS Old Gen (Heap memory): committed=170.50 MB, used=12.22 MB, max=2.67 GB, threshold=0.00 B\n    Memory Pool: PS Perm Gen (Non-heap memory): committed=25.50 MB, used=25.15 MB, max=82.00 MB, threshold=0.00 B\n2015-02-06 00:41:40.815+0000 INFO  [org.neo4j]: Operating system information:\n    Operating System: Mac OS X; version: 10.10.2; arch: x86_64; cpus: 8\n    Max number of file descriptors: 10240\n    Number of open file descriptors: 72\n    Process id: 5385@Dierk-Konigs-MacBook-Pro.local\n    Byte order: LITTLE_ENDIAN\n    Local timezone: Europe/Zurich\n2015-02-06 00:41:40.817+0000 INFO  [org.neo4j]: JVM information:\n    VM Name: Java HotSpot(TM) 64-Bit Server VM\n    VM Vendor: Oracle Corporation\n    VM Version: 24.51-b03\n    JIT compiler: HotSpot 64-Bit Tiered Compilers\n    VM Arguments: [-Dscript.name=/Users/dierkkoenig/.gvm/groovy/2.4.0/bin/groovy, -Dprogram.name=groovy, -Dgroovy.starter.conf=/Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf, -Dgroovy.home=/Users/dierkkoenig/.gvm/groovy/2.4.0, -Dtools.jar=/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar]\n2015-02-06 00:41:40.818+0000 INFO  [org.neo4j]: Java classpath:\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/qdox-1.12.1.jar\n     [loader.3] file:/System/Library/Java/Extensions/dns_sd.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jcommander-1.47.jar\n     [loader.2] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-1.9.4.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jce.jar\n     [loader.3] file:/Users/dierkkoenig/Library/Java/Extensions/libJNPRAuthKit.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/bsf-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/MRJToolkit.jar\n     [loader.3] file:/opt/subversion/lib/libsvnjavahl-1.0.0.0.dylib\n     [loader.3] file:/System/Library/Java/Extensions/vecmath.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/sunrsasign.jar\n     [loader.3] file:/System/Library/Java/Extensions/libmlib_jai.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-groovysh-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-antlr-1.9.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/xmlpull-1.1.3.1.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-bsf-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-nio-2.4.0.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunec.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/servlet-api-2.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-sql-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-xml-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3D.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jsp-api-2.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/mlibwrapper_jai.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-primitive-collections/jars/neo4j-primitive-collections-2.1.6.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.lucene/lucene-core/jars/lucene-core-3.6.2.jar\n     [loader.3] file:/Library/Java/Extensions/librxtxSerial.jnilib\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/localedata.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/charsets.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-ant-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-test-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DAudio.jnilib\n     [loader.3] file:/System/Library/Java/Extensions/libAppleScriptEngine.jnilib\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jfr.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3daudio.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-groovydoc-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-jmx-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DUtils.jnilib\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-kernel/jars/neo4j-kernel-2.1.6.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dcore.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jansi-1.11.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/openbeans-1.0.jar\n     [loader.3] file:/usr/lib/java/libjdns_sd.jnilib\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-junit-1.9.4.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jsse.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jline-2.12.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/zipfs.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dutils.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/classes\n     [loader.3] file:/System/Library/Java/Extensions/jai_core.jar\n     [loader.1] file:/projects/git/regina/listings/chap13/./\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ivy-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-lucene-index/jars/neo4j-lucene-index-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-json-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.groovy/grapes/org.hsqldb/hsqldb/jars/hsqldb-2.3.2.jar\n     [loader.3] file:/System/Library/Java/Extensions/jai_codec.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-console-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-templates-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jsr166y-1.7.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-swing-2.4.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/resources.jar\n     [loader.3] file:/Library/Java/Extensions/RXTXcomm.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/hamcrest-core-1.3.jar\n     [loader.1] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-launcher-1.9.4.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.geronimo.specs/geronimo-jta_1.1_spec/jars/geronimo-jta_1.1_spec-1.1.1.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/dnsns.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-docgenerator-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/multiverse-core-0.7.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/commons-logging-1.2.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/rt.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/xstream-1.4.7.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/commons-cli-1.2.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-jsr223-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/junit-4.12.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-testng-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-servlet-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/AppleScriptEngine.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/testng-6.8.13.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/gpars-1.2.1.jar\n2015-02-06 00:41:40.822+0000 INFO  [org.neo4j]: Library path:\n    /Users/dierkkoenig/Library/Java/Extensions\n    /Library/Java/Extensions\n    /Network/Library/Java/Extensions\n    /System/Library/Java/Extensions\n    /usr/lib/java\n    /projects/git/regina/listings/chap13\n2015-02-06 00:41:40.822+0000 INFO  [org.neo4j]: System.properties:\n    sun.boot.library.path = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib\n    user.country.format = CH\n    gopherProxySet = false\n    path.separator = :\n    file.encoding.pkg = sun.io\n    user.country = DE\n    sun.java.launcher = SUN_STANDARD\n    sun.os.patch.level = unknown\n    program.name = groovy\n    user.dir = /projects/git/regina/listings/chap13\n    tools.jar = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n    sun.jnu.encoding = UTF-8\n    script.name = /Users/dierkkoenig/.gvm/groovy/2.4.0/bin/groovy\n    sun.management.compiler = HotSpot 64-Bit Tiered Compilers\n    http.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    user.home = /Users/dierkkoenig\n    user.timezone = Europe/Zurich\n    file.encoding = UTF-8\n    user.name = dierkkoenig\n    sun.java.command = org.codehaus.groovy.tools.GroovyStarter --main groovy.ui.GroovyMain --conf /Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf --classpath . ../../test\n    sun.arch.data.model = 64\n    user.language = de\n    awt.toolkit = sun.lwawt.macosx.LWCToolkit\n    file.separator = /\n    sun.io.unicode.encoding = UnicodeBig\n    sun.cpu.endian = little\n    groovy.starter.conf = /Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf\n    socksNonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    ftp.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    groovy.home = /Users/dierkkoenig/.gvm/groovy/2.4.0\n    sun.cpu.isalist = \n2015-02-06 00:41:40.822+0000 INFO  [org.neo4j]: Network information:\n    Interface awdl0:\n        address: fe80:0:0:0:10c4:ecff:fed9:b394%8\n    Interface en0:\n        address: fe80:0:0:0:2acf:e9ff:fe19:ca6d%4\n        address: 10.0.1.19\n    Interface lo0:\n        address: fe80:0:0:0:0:0:0:1%1\n        address: 0:0:0:0:0:0:0:1\n        address: 127.0.0.1\n2015-02-06 00:41:40.824+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics END ---\n2015-02-06 00:41:40.900+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=114b)\n2015-02-06 00:41:40.903+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=10b)\n2015-02-06 00:41:40.905+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-02-06 00:41:40.908+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-02-06 00:41:40.910+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.strings] brickCount=0 brickSize=1181696b mappedMem=1181745152b (storeSize=128b)\n2015-02-06 00:41:40.912+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index.keys] brickCount=0 brickSize=0b mappedMem=0b (storeSize=266b)\n2015-02-06 00:41:40.914+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index] brickCount=0 brickSize=0b mappedMem=0b (storeSize=54b)\n2015-02-06 00:41:40.916+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.arrays] brickCount=0 brickSize=1339008b mappedMem=1339031552b (storeSize=128b)\n2015-02-06 00:41:40.934+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db] brickCount=0 brickSize=1390392b mappedMem=1390411776b (storeSize=2460b)\n2015-02-06 00:41:40.939+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipstore.db] brickCount=0 brickSize=1702856b mappedMem=1702887424b (storeSize=1020b)\n2015-02-06 00:41:40.942+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db.labels] brickCount=0 brickSize=0b mappedMem=0b (storeSize=68b)\n2015-02-06 00:41:40.945+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db] brickCount=0 brickSize=385875b mappedMem=385875968b (storeSize=450b)\n2015-02-06 00:41:40.948+0000 INFO  [org.neo4j]: [marathon/neostore.schemastore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=64b)\n2015-02-06 00:41:40.952+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipgroupstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=25b)\n2015-02-06 00:41:40.954+0000 INFO  [org.neo4j]: [marathon/neostore] brickCount=0 brickSize=0b mappedMem=0b (storeSize=81b)\n2015-02-06 00:41:41.222+0000 INFO  [org.neo4j]: Opened logical log [marathon/nioneo_logical.log.1] version=3, lastTxId=12 (clean)\n2015-02-06 00:41:41.227+0000 INFO  [org.neo4j]: TM opening log: marathon/tm_tx_log.1\n2015-02-06 00:41:41.234+0000 INFO  [org.neo4j]: Kernel health set to OK\n2015-02-06 00:41:41.245+0000 INFO  [org.neo4j]: Opened logical log [marathon/index/lucene.log.1] version=3, lastTxId=1 (clean)\n2015-02-06 00:41:41.250+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions START ---\n2015-02-06 00:41:41.250+0000 INFO  [org.neo4j]: Graph Database: org.neo4j.kernel.EmbeddedGraphDatabase StoreId{creationTime=1422808769411, randomId=1762119504651947014, storeVersion=14406081294923270, upgradeTime=1422808769411, upgradeId=1762119504651947014}\n2015-02-06 00:41:41.253+0000 INFO  [org.neo4j]: Kernel version: Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6\n2015-02-06 00:41:41.253+0000 INFO  [org.neo4j]: Neo4j component versions:\n2015-02-06 00:41:41.254+0000 INFO  [org.neo4j]:   Neo4j - Lucene Index (neo4j-lucene-index), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 00:41:41.254+0000 INFO  [org.neo4j]:   Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 00:41:41.254+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions END ---\n2015-02-06 00:41:41.257+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS START ---\n2015-02-06 00:41:41.257+0000 INFO  [org.neo4j]: Store versions:\n    Store versions:\n      NeoStore v0.A.3\n      SchemaStore v0.A.3\n      NodeStore v0.A.3\n      RelationshipStore v0.A.3\n      RelationshipTypeStore v0.A.3\n      LabelTokenStore v0.A.3\n      PropertyStore v0.A.3\n      PropertyIndexStore v0.A.3\n      StringPropertyStore v0.A.3\n      ArrayPropertyStore v0.A.3\n      RelationshipGroupStore v0.A.3\n2015-02-06 00:41:41.258+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS END ---\n2015-02-06 00:41:41.258+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE START ---\n2015-02-06 00:41:41.258+0000 INFO  [org.neo4j]: Id usage:\n    Id usage:\n      SchemaStore: used=1 high=0\n      NodeStore: used=30 high=29\n      RelationshipStore: used=30 high=29\n      RelationshipTypeStore: used=2 high=1\n      LabelTokenStore: used=0 high=-1\n      PropertyStore: used=60 high=59\n      PropertyIndexStore: used=6 high=5\n      StringPropertyStore: used=1 high=0\n      ArrayPropertyStore: used=1 high=0\n      RelationshipGroupStore: used=1 high=0\n2015-02-06 00:41:41.259+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE END ---\n2015-02-06 00:41:41.259+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS START ---\n2015-02-06 00:41:41.259+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS END ---\n2015-02-06 00:41:41.260+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles START ---\n2015-02-06 00:41:41.260+0000 INFO  [org.neo4j]: Disk space on partition (Total / Free / Free %): 499082485760 / 174680444928 / 35\nStorage files: (filename : modification date - size)\n      active_tx_log: 2015-02-01T17:39:29+0100 - 11.00 B\n      index:\n        lucene-store.db: 2015-02-02T02:29:26+0100 - 40.00 B\n        lucene.log.1: 2015-02-06T01:41:41+0100 - 16.00 B\n        lucene.log.active: 2015-02-06T01:41:41+0100 - 4.00 B\n        lucene.log.v0: 2015-02-01T17:39:30+0100 - 16.00 B\n        lucene.log.v1: 2015-02-02T02:28:48+0100 - 16.00 B\n        lucene.log.v2: 2015-02-02T02:29:26+0100 - 16.00 B\n      - Total: 2015-02-06T01:41:41+0100 - 108.00 B\n      lock: 2015-02-06T01:41:40+0100 - 0.00 B\n      messages.log: 2015-02-06T01:41:41+0100 - 95.23 kB\n      neostore: 2015-02-06T01:41:40+0100 - 81.00 B\n      neostore.id: 2015-02-06T01:41:40+0100 - 9.00 B\n      neostore.labeltokenstore.db: 2015-02-06T01:41:40+0100 - 0.00 B\n      neostore.labeltokenstore.db.id: 2015-02-06T01:41:40+0100 - 9.00 B\n      neostore.labeltokenstore.db.names: 2015-02-06T01:41:40+0100 - 38.00 B\n      neostore.labeltokenstore.db.names.id: 2015-02-06T01:41:40+0100 - 9.00 B\n      neostore.nodestore.db: 2015-02-06T01:41:40+0100 - 450.00 B\n      neostore.nodestore.db.id: 2015-02-06T01:41:40+0100 - 9.00 B\n      neostore.nodestore.db.labels: 2015-02-06T01:41:40+0100 - 68.00 B\n      neostore.nodestore.db.labels.id: 2015-02-06T01:41:40+0100 - 9.00 B\n      neostore.propertystore.db: 2015-02-06T01:41:40+0100 - 2.40 kB\n      neostore.propertystore.db.arrays: 2015-02-06T01:41:40+0100 - 128.00 B\n      neostore.propertystore.db.arrays.id: 2015-02-06T01:41:40+0100 - 9.00 B\n      neostore.propertystore.db.id: 2015-02-06T01:41:40+0100 - 9.00 B\n      neostore.propertystore.db.index: 2015-02-06T01:41:40+0100 - 54.00 B\n      neostore.propertystore.db.index.id: 2015-02-06T01:41:40+0100 - 9.00 B\n      neostore.propertystore.db.index.keys: 2015-02-06T01:41:40+0100 - 266.00 B\n      neostore.propertystore.db.index.keys.id: 2015-02-06T01:41:40+0100 - 9.00 B\n      neostore.propertystore.db.strings: 2015-02-06T01:41:40+0100 - 128.00 B\n      neostore.propertystore.db.strings.id: 2015-02-06T01:41:40+0100 - 9.00 B\n      neostore.relationshipgroupstore.db: 2015-02-06T01:41:40+0100 - 25.00 B\n      neostore.relationshipgroupstore.db.id: 2015-02-06T01:41:40+0100 - 9.00 B\n      neostore.relationshipstore.db: 2015-02-06T01:41:40+0100 - 1020.00 B\n      neostore.relationshipstore.db.id: 2015-02-06T01:41:40+0100 - 9.00 B\n      neostore.relationshiptypestore.db: 2015-02-06T01:41:40+0100 - 10.00 B\n      neostore.relationshiptypestore.db.id: 2015-02-06T01:41:40+0100 - 9.00 B\n      neostore.relationshiptypestore.db.names: 2015-02-06T01:41:40+0100 - 114.00 B\n      neostore.relationshiptypestore.db.names.id: 2015-02-06T01:41:40+0100 - 9.00 B\n      neostore.schemastore.db: 2015-02-06T01:41:40+0100 - 64.00 B\n      neostore.schemastore.db.id: 2015-02-06T01:41:40+0100 - 9.00 B\n      nioneo_logical.log.1: 2015-02-06T01:41:41+0100 - 16.00 B\n      nioneo_logical.log.active: 2015-02-06T01:41:41+0100 - 4.00 B\n      nioneo_logical.log.v0: 2015-02-01T17:39:30+0100 - 4.52 kB\n      nioneo_logical.log.v1: 2015-02-02T02:28:48+0100 - 3.34 kB\n      nioneo_logical.log.v2: 2015-02-02T02:29:26+0100 - 3.34 kB\n      schema:\n        label:\n          lucene:\n            segments.gen: 2015-02-01T17:39:30+0100 - 20.00 B\n            segments_1: 2015-02-01T17:39:30+0100 - 32.00 B\n            write.lock: 2015-02-06T01:41:41+0100 - 0.00 B\n          - Total: 2015-02-06T01:41:41+0100 - 52.00 B\n        - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      store_lock: 2015-02-01T17:39:29+0100 - 0.00 B\n      tm_tx_log.1: 2015-02-06T01:41:41+0100 - 0.00 B\n2015-02-06 00:41:41.270+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles END ---\n2015-02-06 00:41:41.317+0000 INFO  [org.neo4j]: Database is now ready\n2015-02-06 00:41:41.545+0000 INFO  [org.neo4j]: Shutdown started\n2015-02-06 00:41:41.546+0000 INFO  [org.neo4j]: Database is now unavailable\n2015-02-06 00:41:41.550+0000 INFO  [org.neo4j]: Closed log marathon/index/lucene.log\n2015-02-06 00:41:41.550+0000 INFO  [org.neo4j]: TM shutting down\n2015-02-06 00:41:41.557+0000 INFO  [org.neo4j]: Closed log marathon/nioneo_logical.log\n2015-02-06 00:41:41.558+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db.names hit=0 miss=4 switches=0 ooe=0\n2015-02-06 00:41:41.559+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db hit=0 miss=2 switches=0 ooe=0\n2015-02-06 00:41:41.560+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db.names hit=0 miss=0 switches=0 ooe=0\n2015-02-06 00:41:41.560+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-06 00:41:41.561+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.strings hit=0 miss=0 switches=0 ooe=0\n2015-02-06 00:41:41.562+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index.keys hit=0 miss=12 switches=0 ooe=0\n2015-02-06 00:41:41.562+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index hit=0 miss=6 switches=0 ooe=0\n2015-02-06 00:41:41.563+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.arrays hit=0 miss=0 switches=0 ooe=0\n2015-02-06 00:41:41.564+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db hit=20 miss=0 switches=0 ooe=0\n2015-02-06 00:41:41.565+0000 INFO  [org.neo4j]: marathon/neostore.relationshipstore.db hit=10 miss=0 switches=0 ooe=0\n2015-02-06 00:41:41.565+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db.labels hit=0 miss=0 switches=0 ooe=0\n2015-02-06 00:41:41.566+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db hit=10 miss=0 switches=0 ooe=0\n2015-02-06 00:41:41.567+0000 INFO  [org.neo4j]: marathon/neostore.schemastore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-06 00:41:41.568+0000 INFO  [org.neo4j]: marathon/neostore.relationshipgroupstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-06 00:41:41.569+0000 INFO  [org.neo4j]: marathon/neostore hit=0 miss=18 switches=0 ooe=0\n2015-02-06 00:41:41.570+0000 INFO  [org.neo4j]: NeoStore closed\n2015-02-06 00:41:41.570+0000 INFO  [org.neo4j]: --- STOPPING diagnostics START ---\n2015-02-06 00:41:41.570+0000 INFO  [org.neo4j]: --- STOPPING diagnostics END ---\n2015-02-06 00:41:42.646+0000 INFO  [org.neo4j]: No locking implementation specified, defaulting to 'community'\n2015-02-06 00:41:42.710+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics START ---\n2015-02-06 00:41:42.712+0000 INFO  [org.neo4j]: Neo4j Kernel properties:\n    neostore.propertystore.db.mapped_memory=1326M\n    neostore.nodestore.db.mapped_memory=368M\n    neostore.relationshipstore.db.mapped_memory=1624M\n    neostore.propertystore.db.strings.mapped_memory=1127M\n    store_dir=marathon\n    neostore.propertystore.db.arrays.mapped_memory=1277M\n    ephemeral=false\n2015-02-06 00:41:42.714+0000 INFO  [org.neo4j]: Diagnostics providers:\n    org.neo4j.kernel.configuration.Config\n    org.neo4j.kernel.info.DiagnosticsManager\n    SYSTEM_MEMORY\n    JAVA_MEMORY\n    OPERATING_SYSTEM\n    JAVA_VIRTUAL_MACHINE\n    CLASSPATH\n    LIBRARY_PATH\n    SYSTEM_PROPERTIES\n    NETWORK\n2015-02-06 00:41:42.714+0000 INFO  [org.neo4j]: System memory information:\n    Total Physical memory: 16.00 GB\n    Free Physical memory: 7.56 GB\n    Committed virtual memory: 6.81 GB\n    Total swap space: 2.00 GB\n    Free swap space: 1.19 GB\n2015-02-06 00:41:42.715+0000 INFO  [org.neo4j]: JVM memory information:\n    Free  memory: 172.99 MB\n    Total memory: 310.00 MB\n    Max   memory: 3.56 GB\n    Garbage Collector: PS Scavenge: [PS Eden Space, PS Survivor Space]\n    Garbage Collector: PS MarkSweep: [PS Eden Space, PS Survivor Space, PS Old Gen, PS Perm Gen]\n    Memory Pool: Code Cache (Non-heap memory): committed=4.06 MB, used=4.00 MB, max=48.00 MB, threshold=0.00 B\n    Memory Pool: PS Eden Space (Heap memory): committed=129.00 MB, used=104.62 MB, max=1.30 GB, threshold=?\n    Memory Pool: PS Survivor Space (Heap memory): committed=10.50 MB, used=10.47 MB, max=10.50 MB, threshold=?\n    Memory Pool: PS Old Gen (Heap memory): committed=170.50 MB, used=21.92 MB, max=2.67 GB, threshold=0.00 B\n    Memory Pool: PS Perm Gen (Non-heap memory): committed=33.50 MB, used=33.45 MB, max=82.00 MB, threshold=0.00 B\n2015-02-06 00:41:42.717+0000 INFO  [org.neo4j]: Operating system information:\n    Operating System: Mac OS X; version: 10.10.2; arch: x86_64; cpus: 8\n    Max number of file descriptors: 10240\n    Number of open file descriptors: 95\n    Process id: 5385@Dierk-Konigs-MacBook-Pro.local\n    Byte order: LITTLE_ENDIAN\n    Local timezone: Europe/Zurich\n2015-02-06 00:41:42.718+0000 INFO  [org.neo4j]: JVM information:\n    VM Name: Java HotSpot(TM) 64-Bit Server VM\n    VM Vendor: Oracle Corporation\n    VM Version: 24.51-b03\n    JIT compiler: HotSpot 64-Bit Tiered Compilers\n    VM Arguments: [-Dscript.name=/Users/dierkkoenig/.gvm/groovy/2.4.0/bin/groovy, -Dprogram.name=groovy, -Dgroovy.starter.conf=/Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf, -Dgroovy.home=/Users/dierkkoenig/.gvm/groovy/2.4.0, -Dtools.jar=/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar]\n2015-02-06 00:41:42.718+0000 INFO  [org.neo4j]: Java classpath:\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/qdox-1.12.1.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.parboiled/parboiled-scala_2.10/jars/parboiled-scala_2.10-1.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jcommander-1.47.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/bsf-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-configuration/commons-configuration/jars/commons-configuration-1.6.jar\n     [loader.3] file:/Users/dierkkoenig/Library/Java/Extensions/libJNPRAuthKit.jnilib\n     [loader.3] file:/System/Library/Java/Extensions/vecmath.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-groovysh-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-logging/commons-logging/jars/commons-logging-1.1.1.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-antlr-1.9.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/xmlpull-1.1.3.1.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunec.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3D.jnilib\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-lang/commons-lang/jars/commons-lang-2.4.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/localedata.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/charsets.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3daudio.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dcore.jar\n     [loader.3] file:/usr/lib/java/libjdns_sd.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-junit-1.9.4.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-management/jars/neo4j-management-2.1.6.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/zipfs.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.gremlin/gremlin-groovy/jars/gremlin-groovy-2.6.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/classes\n     [loader.3] file:/System/Library/Java/Extensions/jai_core.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ivy-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-json-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-templates-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.gremlin/gremlin-java/jars/gremlin-java-2.6.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/hamcrest-core-1.3.jar\n     [loader.3] file:/Library/Java/Extensions/RXTXcomm.jar\n     [loader.1] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.geronimo.specs/geronimo-jta_1.1_spec/jars/geronimo-jta_1.1_spec-1.1.1.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/dnsns.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/multiverse-core-0.7.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-commons/jars/neo4j-cypher-commons-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/junit-4.12.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-servlet-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/AppleScriptEngine.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/testng-6.8.13.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.parboiled/parboiled-core/jars/parboiled-core-1.1.6.jar\n     [loader.3] file:/System/Library/Java/Extensions/dns_sd.jar\n     [loader.2] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-1.9.4.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jce.jar\n     [loader.3] file:/System/Library/Java/Extensions/MRJToolkit.jar\n     [loader.3] file:/opt/subversion/lib/libsvnjavahl-1.0.0.0.dylib\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-beanutils/commons-beanutils/jars/commons-beanutils-1.7.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/sunrsasign.jar\n     [loader.3] file:/System/Library/Java/Extensions/libmlib_jai.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-bsf-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-nio-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/servlet-api-2.4.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-digester/commons-digester/jars/commons-digester-1.8.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-sql-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-xml-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jsp-api-2.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-compiler-2.0/jars/neo4j-cypher-compiler-2.0-2.0.4.jar\n     [loader.3] file:/System/Library/Java/Extensions/mlibwrapper_jai.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-primitive-collections/jars/neo4j-primitive-collections-2.1.6.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.lucene/lucene-core/jars/lucene-core-3.6.2.jar\n     [loader.3] file:/Library/Java/Extensions/librxtxSerial.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-ant-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher/jars/neo4j-cypher-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-test-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DAudio.jnilib\n     [loader.3] file:/System/Library/Java/Extensions/libAppleScriptEngine.jnilib\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jfr.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.scala-lang/scala-library/jars/scala-library-2.10.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-groovydoc-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-jmx-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DUtils.jnilib\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-kernel/jars/neo4j-kernel-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jansi-1.11.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/openbeans-1.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jsse.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jline-2.12.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dutils.jar\n     [loader.1] file:/projects/git/regina/listings/chap13/./\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-lucene-index/jars/neo4j-lucene-index-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.groovy/grapes/org.hsqldb/hsqldb/jars/hsqldb-2.3.2.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar\n     [loader.3] file:/System/Library/Java/Extensions/jai_codec.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-beanutils/commons-beanutils-core/jars/commons-beanutils-core-1.8.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-console-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.blueprints/blueprints-neo4j2-graph/jars/blueprints-neo4j2-graph-2.6.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jsr166y-1.7.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.blueprints/blueprints-core/jars/blueprints-core-2.6.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-swing-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-compiler-2.1/jars/neo4j-cypher-compiler-2.1-2.1.6.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/resources.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-launcher-1.9.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-docgenerator-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/commons-logging-1.2.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/rt.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/xstream-1.4.7.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/commons-cli-1.2.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-jsr223-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-testng-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-collections/commons-collections/jars/commons-collections-3.2.1.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop/pipes/jars/pipes-2.6.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.googlecode.concurrentlinkedhashmap/concurrentlinkedhashmap-lru/jars/concurrentlinkedhashmap-lru-1.4.1.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/gpars-1.2.1.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-compiler-1.9/jars/neo4j-cypher-compiler-1.9-2.0.4.jar\n2015-02-06 00:41:42.722+0000 INFO  [org.neo4j]: Library path:\n    /Users/dierkkoenig/Library/Java/Extensions\n    /Library/Java/Extensions\n    /Network/Library/Java/Extensions\n    /System/Library/Java/Extensions\n    /usr/lib/java\n    /projects/git/regina/listings/chap13\n2015-02-06 00:41:42.722+0000 INFO  [org.neo4j]: System.properties:\n    sun.boot.library.path = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib\n    user.country.format = CH\n    gopherProxySet = false\n    path.separator = :\n    file.encoding.pkg = sun.io\n    user.country = DE\n    sun.java.launcher = SUN_STANDARD\n    sun.os.patch.level = unknown\n    program.name = groovy\n    user.dir = /projects/git/regina/listings/chap13\n    tools.jar = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n    sun.jnu.encoding = UTF-8\n    script.name = /Users/dierkkoenig/.gvm/groovy/2.4.0/bin/groovy\n    sun.management.compiler = HotSpot 64-Bit Tiered Compilers\n    http.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    user.home = /Users/dierkkoenig\n    user.timezone = Europe/Zurich\n    file.encoding = UTF-8\n    user.name = dierkkoenig\n    sun.java.command = org.codehaus.groovy.tools.GroovyStarter --main groovy.ui.GroovyMain --conf /Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf --classpath . ../../test\n    sun.arch.data.model = 64\n    user.language = de\n    awt.toolkit = sun.lwawt.macosx.LWCToolkit\n    file.separator = /\n    sun.io.unicode.encoding = UnicodeBig\n    sun.cpu.endian = little\n    groovy.starter.conf = /Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf\n    socksNonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    ftp.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    groovy.home = /Users/dierkkoenig/.gvm/groovy/2.4.0\n    sun.cpu.isalist = \n2015-02-06 00:41:42.723+0000 INFO  [org.neo4j]: Network information:\n    Interface awdl0:\n        address: fe80:0:0:0:10c4:ecff:fed9:b394%8\n    Interface en0:\n        address: fe80:0:0:0:2acf:e9ff:fe19:ca6d%4\n        address: 10.0.1.19\n    Interface lo0:\n        address: fe80:0:0:0:0:0:0:1%1\n        address: 0:0:0:0:0:0:0:1\n        address: 127.0.0.1\n2015-02-06 00:41:42.723+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics END ---\n2015-02-06 00:41:42.767+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=114b)\n2015-02-06 00:41:42.768+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=10b)\n2015-02-06 00:41:42.769+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-02-06 00:41:42.769+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-02-06 00:41:42.770+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.strings] brickCount=0 brickSize=1181696b mappedMem=1181745152b (storeSize=128b)\n2015-02-06 00:41:42.770+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index.keys] brickCount=0 brickSize=0b mappedMem=0b (storeSize=266b)\n2015-02-06 00:41:42.770+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index] brickCount=0 brickSize=0b mappedMem=0b (storeSize=54b)\n2015-02-06 00:41:42.771+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.arrays] brickCount=0 brickSize=1339008b mappedMem=1339031552b (storeSize=128b)\n2015-02-06 00:41:42.788+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db] brickCount=0 brickSize=1390392b mappedMem=1390411776b (storeSize=3280b)\n2015-02-06 00:41:42.791+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipstore.db] brickCount=0 brickSize=1702856b mappedMem=1702887424b (storeSize=1360b)\n2015-02-06 00:41:42.791+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db.labels] brickCount=0 brickSize=0b mappedMem=0b (storeSize=68b)\n2015-02-06 00:41:42.793+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db] brickCount=0 brickSize=385875b mappedMem=385875968b (storeSize=600b)\n2015-02-06 00:41:42.794+0000 INFO  [org.neo4j]: [marathon/neostore.schemastore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=64b)\n2015-02-06 00:41:42.795+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipgroupstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=25b)\n2015-02-06 00:41:42.796+0000 INFO  [org.neo4j]: [marathon/neostore] brickCount=0 brickSize=0b mappedMem=0b (storeSize=81b)\n2015-02-06 00:41:42.971+0000 INFO  [org.neo4j]: Opened logical log [marathon/nioneo_logical.log.1] version=4, lastTxId=13 (clean)\n2015-02-06 00:41:42.976+0000 INFO  [org.neo4j]: TM opening log: marathon/tm_tx_log.1\n2015-02-06 00:41:42.980+0000 INFO  [org.neo4j]: Kernel health set to OK\n2015-02-06 00:41:42.988+0000 INFO  [org.neo4j]: Opened logical log [marathon/index/lucene.log.1] version=4, lastTxId=1 (clean)\n2015-02-06 00:41:42.991+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions START ---\n2015-02-06 00:41:42.991+0000 INFO  [org.neo4j]: Graph Database: org.neo4j.kernel.EmbeddedGraphDatabase StoreId{creationTime=1422808769411, randomId=1762119504651947014, storeVersion=14406081294923270, upgradeTime=1422808769411, upgradeId=1762119504651947014}\n2015-02-06 00:41:43.007+0000 INFO  [org.neo4j]: Kernel version: Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6\n2015-02-06 00:41:43.007+0000 INFO  [org.neo4j]: Neo4j component versions:\n2015-02-06 00:41:43.010+0000 INFO  [org.neo4j]:   Neo4j - Lucene Index (neo4j-lucene-index), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 00:41:43.010+0000 INFO  [org.neo4j]:   Neo4j - Cypher Compiler 2.1 (neo4j-cypher-compiler-2.1), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 00:41:43.010+0000 INFO  [org.neo4j]:   Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 00:41:43.010+0000 INFO  [org.neo4j]:   Neo4j - Cypher (neo4j-cypher), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 00:41:43.010+0000 INFO  [org.neo4j]:   Neo4j - Graph DB Monitoring and Management tools (neo4j-management), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 00:41:43.010+0000 INFO  [org.neo4j]:   Neo4j - Cypher Compiler 2.0 (neo4j-cypher-compiler-2.0), version: 2.0.4; revision: 2.0.4:2.0-maint:130/4a7d10bc274a5d26a180bbe9df25100e8a694748\n2015-02-06 00:41:43.010+0000 INFO  [org.neo4j]:   Neo4j - Cypher Compiler 1.9 (neo4j-cypher-compiler-1.9), version: 2.0.4; revision: 2.0.4:2.0-maint:130/4a7d10bc274a5d26a180bbe9df25100e8a694748\n2015-02-06 00:41:43.010+0000 INFO  [org.neo4j]:   Neo4j - Cypher Commons (neo4j-cypher-commons), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 00:41:43.010+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions END ---\n2015-02-06 00:41:43.012+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS START ---\n2015-02-06 00:41:43.012+0000 INFO  [org.neo4j]: Store versions:\n    Store versions:\n      NeoStore v0.A.3\n      SchemaStore v0.A.3\n      NodeStore v0.A.3\n      RelationshipStore v0.A.3\n      RelationshipTypeStore v0.A.3\n      LabelTokenStore v0.A.3\n      PropertyStore v0.A.3\n      PropertyIndexStore v0.A.3\n      StringPropertyStore v0.A.3\n      ArrayPropertyStore v0.A.3\n      RelationshipGroupStore v0.A.3\n2015-02-06 00:41:43.013+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS END ---\n2015-02-06 00:41:43.013+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE START ---\n2015-02-06 00:41:43.013+0000 INFO  [org.neo4j]: Id usage:\n    Id usage:\n      SchemaStore: used=1 high=0\n      NodeStore: used=40 high=39\n      RelationshipStore: used=40 high=39\n      RelationshipTypeStore: used=2 high=1\n      LabelTokenStore: used=0 high=-1\n      PropertyStore: used=80 high=79\n      PropertyIndexStore: used=6 high=5\n      StringPropertyStore: used=1 high=0\n      ArrayPropertyStore: used=1 high=0\n      RelationshipGroupStore: used=1 high=0\n2015-02-06 00:41:43.013+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE END ---\n2015-02-06 00:41:43.013+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS START ---\n2015-02-06 00:41:43.013+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS END ---\n2015-02-06 00:41:43.014+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles START ---\n2015-02-06 00:41:43.014+0000 INFO  [org.neo4j]: Disk space on partition (Total / Free / Free %): 499082485760 / 174680317952 / 35\nStorage files: (filename : modification date - size)\n      active_tx_log: 2015-02-01T17:39:29+0100 - 11.00 B\n      index:\n        lucene-store.db: 2015-02-06T01:41:41+0100 - 40.00 B\n        lucene.log.1: 2015-02-06T01:41:43+0100 - 16.00 B\n        lucene.log.active: 2015-02-06T01:41:42+0100 - 4.00 B\n        lucene.log.v0: 2015-02-01T17:39:30+0100 - 16.00 B\n        lucene.log.v1: 2015-02-02T02:28:48+0100 - 16.00 B\n        lucene.log.v2: 2015-02-02T02:29:26+0100 - 16.00 B\n        lucene.log.v3: 2015-02-06T01:41:41+0100 - 16.00 B\n      - Total: 2015-02-06T01:41:42+0100 - 124.00 B\n      lock: 2015-02-06T01:41:42+0100 - 0.00 B\n      messages.log: 2015-02-06T01:41:43+0100 - 122.37 kB\n      neostore: 2015-02-06T01:41:42+0100 - 81.00 B\n      neostore.id: 2015-02-06T01:41:42+0100 - 9.00 B\n      neostore.labeltokenstore.db: 2015-02-06T01:41:42+0100 - 0.00 B\n      neostore.labeltokenstore.db.id: 2015-02-06T01:41:42+0100 - 9.00 B\n      neostore.labeltokenstore.db.names: 2015-02-06T01:41:42+0100 - 38.00 B\n      neostore.labeltokenstore.db.names.id: 2015-02-06T01:41:42+0100 - 9.00 B\n      neostore.nodestore.db: 2015-02-06T01:41:42+0100 - 600.00 B\n      neostore.nodestore.db.id: 2015-02-06T01:41:42+0100 - 9.00 B\n      neostore.nodestore.db.labels: 2015-02-06T01:41:42+0100 - 68.00 B\n      neostore.nodestore.db.labels.id: 2015-02-06T01:41:42+0100 - 9.00 B\n      neostore.propertystore.db: 2015-02-06T01:41:42+0100 - 3.20 kB\n      neostore.propertystore.db.arrays: 2015-02-06T01:41:42+0100 - 128.00 B\n      neostore.propertystore.db.arrays.id: 2015-02-06T01:41:42+0100 - 9.00 B\n      neostore.propertystore.db.id: 2015-02-06T01:41:42+0100 - 9.00 B\n      neostore.propertystore.db.index: 2015-02-06T01:41:42+0100 - 54.00 B\n      neostore.propertystore.db.index.id: 2015-02-06T01:41:42+0100 - 9.00 B\n      neostore.propertystore.db.index.keys: 2015-02-06T01:41:42+0100 - 266.00 B\n      neostore.propertystore.db.index.keys.id: 2015-02-06T01:41:42+0100 - 9.00 B\n      neostore.propertystore.db.strings: 2015-02-06T01:41:42+0100 - 128.00 B\n      neostore.propertystore.db.strings.id: 2015-02-06T01:41:42+0100 - 9.00 B\n      neostore.relationshipgroupstore.db: 2015-02-06T01:41:42+0100 - 25.00 B\n      neostore.relationshipgroupstore.db.id: 2015-02-06T01:41:42+0100 - 9.00 B\n      neostore.relationshipstore.db: 2015-02-06T01:41:42+0100 - 1.33 kB\n      neostore.relationshipstore.db.id: 2015-02-06T01:41:42+0100 - 9.00 B\n      neostore.relationshiptypestore.db: 2015-02-06T01:41:42+0100 - 10.00 B\n      neostore.relationshiptypestore.db.id: 2015-02-06T01:41:42+0100 - 9.00 B\n      neostore.relationshiptypestore.db.names: 2015-02-06T01:41:42+0100 - 114.00 B\n      neostore.relationshiptypestore.db.names.id: 2015-02-06T01:41:42+0100 - 9.00 B\n      neostore.schemastore.db: 2015-02-06T01:41:42+0100 - 64.00 B\n      neostore.schemastore.db.id: 2015-02-06T01:41:42+0100 - 9.00 B\n      nioneo_logical.log.1: 2015-02-06T01:41:43+0100 - 16.00 B\n      nioneo_logical.log.active: 2015-02-06T01:41:42+0100 - 4.00 B\n      nioneo_logical.log.v0: 2015-02-01T17:39:30+0100 - 4.52 kB\n      nioneo_logical.log.v1: 2015-02-02T02:28:48+0100 - 3.34 kB\n      nioneo_logical.log.v2: 2015-02-02T02:29:26+0100 - 3.34 kB\n      nioneo_logical.log.v3: 2015-02-06T01:41:41+0100 - 3.34 kB\n      schema:\n        label:\n          lucene:\n            segments.gen: 2015-02-01T17:39:30+0100 - 20.00 B\n            segments_1: 2015-02-01T17:39:30+0100 - 32.00 B\n            write.lock: 2015-02-06T01:41:42+0100 - 0.00 B\n          - Total: 2015-02-06T01:41:42+0100 - 52.00 B\n        - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      store_lock: 2015-02-01T17:39:29+0100 - 0.00 B\n      tm_tx_log.1: 2015-02-06T01:41:42+0100 - 0.00 B\n2015-02-06 00:41:43.022+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles END ---\n2015-02-06 00:41:43.063+0000 INFO  [org.neo4j]: Database is now ready\n2015-02-06 00:41:44.296+0000 INFO  [org.neo4j]: Shutdown started\n2015-02-06 00:41:44.297+0000 INFO  [org.neo4j]: Database is now unavailable\n2015-02-06 00:41:44.304+0000 INFO  [org.neo4j]: Closed log marathon/index/lucene.log\n2015-02-06 00:41:44.305+0000 INFO  [org.neo4j]: TM shutting down\n2015-02-06 00:41:44.311+0000 INFO  [org.neo4j]: Closed log marathon/nioneo_logical.log\n2015-02-06 00:41:44.312+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db.names hit=0 miss=4 switches=0 ooe=0\n2015-02-06 00:41:44.313+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db hit=0 miss=2 switches=0 ooe=0\n2015-02-06 00:41:44.314+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db.names hit=0 miss=0 switches=0 ooe=0\n2015-02-06 00:41:44.315+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-06 00:41:44.315+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.strings hit=0 miss=0 switches=0 ooe=0\n2015-02-06 00:41:44.316+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index.keys hit=0 miss=12 switches=0 ooe=0\n2015-02-06 00:41:44.317+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index hit=0 miss=6 switches=0 ooe=0\n2015-02-06 00:41:44.318+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.arrays hit=0 miss=0 switches=0 ooe=0\n2015-02-06 00:41:44.319+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db hit=100 miss=0 switches=0 ooe=0\n2015-02-06 00:41:44.320+0000 INFO  [org.neo4j]: marathon/neostore.relationshipstore.db hit=58 miss=0 switches=0 ooe=0\n2015-02-06 00:41:44.320+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db.labels hit=0 miss=0 switches=0 ooe=0\n2015-02-06 00:41:44.321+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db hit=110 miss=0 switches=0 ooe=0\n2015-02-06 00:41:44.322+0000 INFO  [org.neo4j]: marathon/neostore.schemastore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-06 00:41:44.323+0000 INFO  [org.neo4j]: marathon/neostore.relationshipgroupstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-06 00:41:44.324+0000 INFO  [org.neo4j]: marathon/neostore hit=0 miss=18 switches=0 ooe=0\n2015-02-06 00:41:44.325+0000 INFO  [org.neo4j]: NeoStore closed\n2015-02-06 00:41:44.325+0000 INFO  [org.neo4j]: --- STOPPING diagnostics START ---\n2015-02-06 00:41:44.325+0000 INFO  [org.neo4j]: --- STOPPING diagnostics END ---\n2015-02-06 16:00:28.468+0000 INFO  [org.neo4j]: No locking implementation specified, defaulting to 'community'\n2015-02-06 16:00:28.566+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics START ---\n2015-02-06 16:00:28.568+0000 INFO  [org.neo4j]: Neo4j Kernel properties:\n    neostore.propertystore.db.mapped_memory=1326M\n    neostore.nodestore.db.mapped_memory=368M\n    neostore.relationshipstore.db.mapped_memory=1624M\n    neostore.propertystore.db.strings.mapped_memory=1127M\n    store_dir=marathon\n    neostore.propertystore.db.arrays.mapped_memory=1277M\n    ephemeral=false\n2015-02-06 16:00:28.571+0000 INFO  [org.neo4j]: Diagnostics providers:\n    org.neo4j.kernel.configuration.Config\n    org.neo4j.kernel.info.DiagnosticsManager\n    SYSTEM_MEMORY\n    JAVA_MEMORY\n    OPERATING_SYSTEM\n    JAVA_VIRTUAL_MACHINE\n    CLASSPATH\n    LIBRARY_PATH\n    SYSTEM_PROPERTIES\n    NETWORK\n2015-02-06 16:00:28.573+0000 INFO  [org.neo4j]: System memory information:\n    Total Physical memory: 16.00 GB\n    Free Physical memory: 4.74 GB\n    Committed virtual memory: 6.81 GB\n    Total swap space: 2.00 GB\n    Free swap space: 1.60 GB\n2015-02-06 16:00:28.577+0000 INFO  [org.neo4j]: JVM memory information:\n    Free  memory: 259.83 MB\n    Total memory: 310.00 MB\n    Max   memory: 3.56 GB\n    Garbage Collector: PS Scavenge: [PS Eden Space, PS Survivor Space]\n    Garbage Collector: PS MarkSweep: [PS Eden Space, PS Survivor Space, PS Old Gen, PS Perm Gen]\n    Memory Pool: Code Cache (Non-heap memory): committed=3.19 MB, used=3.05 MB, max=48.00 MB, threshold=0.00 B\n    Memory Pool: PS Eden Space (Heap memory): committed=129.00 MB, used=27.64 MB, max=1.31 GB, threshold=?\n    Memory Pool: PS Survivor Space (Heap memory): committed=10.50 MB, used=10.49 MB, max=10.50 MB, threshold=?\n    Memory Pool: PS Old Gen (Heap memory): committed=170.50 MB, used=12.04 MB, max=2.67 GB, threshold=0.00 B\n    Memory Pool: PS Perm Gen (Non-heap memory): committed=25.50 MB, used=25.15 MB, max=82.00 MB, threshold=0.00 B\n2015-02-06 16:00:28.582+0000 INFO  [org.neo4j]: Operating system information:\n    Operating System: Mac OS X; version: 10.10.2; arch: x86_64; cpus: 8\n    Max number of file descriptors: 10240\n    Number of open file descriptors: 71\n    Process id: 6465@Dierk-Konigs-MacBook-Pro.local\n    Byte order: LITTLE_ENDIAN\n    Local timezone: Europe/Zurich\n2015-02-06 16:00:28.584+0000 INFO  [org.neo4j]: JVM information:\n    VM Name: Java HotSpot(TM) 64-Bit Server VM\n    VM Vendor: Oracle Corporation\n    VM Version: 24.51-b03\n    JIT compiler: HotSpot 64-Bit Tiered Compilers\n    VM Arguments: [-Dscript.name=/Users/dierkkoenig/.gvm/groovy/2.4.0/bin/groovy, -Dprogram.name=groovy, -Dgroovy.starter.conf=/Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf, -Dgroovy.home=/Users/dierkkoenig/.gvm/groovy/2.4.0, -Dtools.jar=/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar]\n2015-02-06 16:00:28.584+0000 INFO  [org.neo4j]: Java classpath:\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/qdox-1.12.1.jar\n     [loader.3] file:/System/Library/Java/Extensions/dns_sd.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jcommander-1.47.jar\n     [loader.2] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-1.9.4.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jce.jar\n     [loader.3] file:/Users/dierkkoenig/Library/Java/Extensions/libJNPRAuthKit.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/bsf-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/MRJToolkit.jar\n     [loader.3] file:/opt/subversion/lib/libsvnjavahl-1.0.0.0.dylib\n     [loader.3] file:/System/Library/Java/Extensions/vecmath.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/sunrsasign.jar\n     [loader.3] file:/System/Library/Java/Extensions/libmlib_jai.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-groovysh-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-antlr-1.9.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/xmlpull-1.1.3.1.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-bsf-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-nio-2.4.0.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunec.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/servlet-api-2.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-sql-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-xml-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3D.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jsp-api-2.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/mlibwrapper_jai.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-primitive-collections/jars/neo4j-primitive-collections-2.1.6.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.lucene/lucene-core/jars/lucene-core-3.6.2.jar\n     [loader.3] file:/Library/Java/Extensions/librxtxSerial.jnilib\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/localedata.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/charsets.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-ant-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-test-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DAudio.jnilib\n     [loader.3] file:/System/Library/Java/Extensions/libAppleScriptEngine.jnilib\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jfr.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3daudio.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-groovydoc-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-jmx-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DUtils.jnilib\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-kernel/jars/neo4j-kernel-2.1.6.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dcore.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jansi-1.11.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/openbeans-1.0.jar\n     [loader.3] file:/usr/lib/java/libjdns_sd.jnilib\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-junit-1.9.4.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jsse.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jline-2.12.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/zipfs.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dutils.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/classes\n     [loader.3] file:/System/Library/Java/Extensions/jai_core.jar\n     [loader.1] file:/projects/git/regina/listings/chap13/./\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ivy-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-lucene-index/jars/neo4j-lucene-index-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-json-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.groovy/grapes/org.hsqldb/hsqldb/jars/hsqldb-2.3.2.jar\n     [loader.3] file:/System/Library/Java/Extensions/jai_codec.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-console-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-templates-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jsr166y-1.7.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-swing-2.4.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/resources.jar\n     [loader.3] file:/Library/Java/Extensions/RXTXcomm.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/hamcrest-core-1.3.jar\n     [loader.1] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-launcher-1.9.4.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.geronimo.specs/geronimo-jta_1.1_spec/jars/geronimo-jta_1.1_spec-1.1.1.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/dnsns.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-docgenerator-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/multiverse-core-0.7.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/commons-logging-1.2.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/rt.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/xstream-1.4.7.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/commons-cli-1.2.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-jsr223-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/junit-4.12.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-testng-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-servlet-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/AppleScriptEngine.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/testng-6.8.13.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/gpars-1.2.1.jar\n2015-02-06 16:00:28.588+0000 INFO  [org.neo4j]: Library path:\n    /Users/dierkkoenig/Library/Java/Extensions\n    /Library/Java/Extensions\n    /Network/Library/Java/Extensions\n    /System/Library/Java/Extensions\n    /usr/lib/java\n    /projects/git/regina/listings/chap13\n2015-02-06 16:00:28.588+0000 INFO  [org.neo4j]: System.properties:\n    sun.boot.library.path = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib\n    user.country.format = CH\n    gopherProxySet = false\n    path.separator = :\n    file.encoding.pkg = sun.io\n    user.country = DE\n    sun.java.launcher = SUN_STANDARD\n    sun.os.patch.level = unknown\n    program.name = groovy\n    user.dir = /projects/git/regina/listings/chap13\n    tools.jar = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n    sun.jnu.encoding = UTF-8\n    script.name = /Users/dierkkoenig/.gvm/groovy/2.4.0/bin/groovy\n    sun.management.compiler = HotSpot 64-Bit Tiered Compilers\n    http.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    user.home = /Users/dierkkoenig\n    user.timezone = Europe/Zurich\n    file.encoding = UTF-8\n    user.name = dierkkoenig\n    sun.java.command = org.codehaus.groovy.tools.GroovyStarter --main groovy.ui.GroovyMain --conf /Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf --classpath . ../../test\n    sun.arch.data.model = 64\n    user.language = de\n    awt.toolkit = sun.lwawt.macosx.LWCToolkit\n    file.separator = /\n    sun.io.unicode.encoding = UnicodeBig\n    sun.cpu.endian = little\n    groovy.starter.conf = /Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf\n    socksNonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    ftp.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    groovy.home = /Users/dierkkoenig/.gvm/groovy/2.4.0\n    sun.cpu.isalist = \n2015-02-06 16:00:28.589+0000 INFO  [org.neo4j]: Network information:\n    Interface awdl0:\n        address: fe80:0:0:0:10c4:ecff:fed9:b394%8\n    Interface en0:\n        address: fe80:0:0:0:2acf:e9ff:fe19:ca6d%4\n        address: 10.0.1.19\n    Interface lo0:\n        address: fe80:0:0:0:0:0:0:1%1\n        address: 0:0:0:0:0:0:0:1\n        address: 127.0.0.1\n2015-02-06 16:00:28.592+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics END ---\n2015-02-06 16:00:28.667+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=114b)\n2015-02-06 16:00:28.669+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=10b)\n2015-02-06 16:00:28.671+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-02-06 16:00:28.673+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-02-06 16:00:28.675+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.strings] brickCount=0 brickSize=1181696b mappedMem=1181745152b (storeSize=128b)\n2015-02-06 16:00:28.677+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index.keys] brickCount=0 brickSize=0b mappedMem=0b (storeSize=266b)\n2015-02-06 16:00:28.678+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index] brickCount=0 brickSize=0b mappedMem=0b (storeSize=54b)\n2015-02-06 16:00:28.681+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.arrays] brickCount=0 brickSize=1339008b mappedMem=1339031552b (storeSize=128b)\n2015-02-06 16:00:28.699+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db] brickCount=0 brickSize=1390392b mappedMem=1390411776b (storeSize=4100b)\n2015-02-06 16:00:28.703+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipstore.db] brickCount=0 brickSize=1702856b mappedMem=1702887424b (storeSize=1700b)\n2015-02-06 16:00:28.705+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db.labels] brickCount=0 brickSize=0b mappedMem=0b (storeSize=68b)\n2015-02-06 16:00:28.708+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db] brickCount=0 brickSize=385875b mappedMem=385875968b (storeSize=750b)\n2015-02-06 16:00:28.711+0000 INFO  [org.neo4j]: [marathon/neostore.schemastore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=64b)\n2015-02-06 16:00:28.714+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipgroupstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=25b)\n2015-02-06 16:00:28.716+0000 INFO  [org.neo4j]: [marathon/neostore] brickCount=0 brickSize=0b mappedMem=0b (storeSize=81b)\n2015-02-06 16:00:28.955+0000 INFO  [org.neo4j]: Opened logical log [marathon/nioneo_logical.log.1] version=5, lastTxId=14 (clean)\n2015-02-06 16:00:28.961+0000 INFO  [org.neo4j]: TM opening log: marathon/tm_tx_log.1\n2015-02-06 16:00:28.968+0000 INFO  [org.neo4j]: Kernel health set to OK\n2015-02-06 16:00:28.979+0000 INFO  [org.neo4j]: Opened logical log [marathon/index/lucene.log.1] version=5, lastTxId=1 (clean)\n2015-02-06 16:00:28.984+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions START ---\n2015-02-06 16:00:28.984+0000 INFO  [org.neo4j]: Graph Database: org.neo4j.kernel.EmbeddedGraphDatabase StoreId{creationTime=1422808769411, randomId=1762119504651947014, storeVersion=14406081294923270, upgradeTime=1422808769411, upgradeId=1762119504651947014}\n2015-02-06 16:00:28.987+0000 INFO  [org.neo4j]: Kernel version: Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6\n2015-02-06 16:00:28.987+0000 INFO  [org.neo4j]: Neo4j component versions:\n2015-02-06 16:00:28.988+0000 INFO  [org.neo4j]:   Neo4j - Lucene Index (neo4j-lucene-index), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 16:00:28.988+0000 INFO  [org.neo4j]:   Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 16:00:28.988+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions END ---\n2015-02-06 16:00:28.990+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS START ---\n2015-02-06 16:00:28.991+0000 INFO  [org.neo4j]: Store versions:\n    Store versions:\n      NeoStore v0.A.3\n      SchemaStore v0.A.3\n      NodeStore v0.A.3\n      RelationshipStore v0.A.3\n      RelationshipTypeStore v0.A.3\n      LabelTokenStore v0.A.3\n      PropertyStore v0.A.3\n      PropertyIndexStore v0.A.3\n      StringPropertyStore v0.A.3\n      ArrayPropertyStore v0.A.3\n      RelationshipGroupStore v0.A.3\n2015-02-06 16:00:28.991+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS END ---\n2015-02-06 16:00:28.991+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE START ---\n2015-02-06 16:00:28.991+0000 INFO  [org.neo4j]: Id usage:\n    Id usage:\n      SchemaStore: used=1 high=0\n      NodeStore: used=50 high=49\n      RelationshipStore: used=50 high=49\n      RelationshipTypeStore: used=2 high=1\n      LabelTokenStore: used=0 high=-1\n      PropertyStore: used=100 high=99\n      PropertyIndexStore: used=6 high=5\n      StringPropertyStore: used=1 high=0\n      ArrayPropertyStore: used=1 high=0\n      RelationshipGroupStore: used=1 high=0\n2015-02-06 16:00:28.992+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE END ---\n2015-02-06 16:00:28.992+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS START ---\n2015-02-06 16:00:28.992+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS END ---\n2015-02-06 16:00:28.992+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles START ---\n2015-02-06 16:00:28.993+0000 INFO  [org.neo4j]: Disk space on partition (Total / Free / Free %): 499082485760 / 174966755328 / 35\nStorage files: (filename : modification date - size)\n      active_tx_log: 2015-02-01T17:39:29+0100 - 11.00 B\n      index:\n        lucene-store.db: 2015-02-06T01:41:44+0100 - 40.00 B\n        lucene.log.1: 2015-02-06T17:00:28+0100 - 16.00 B\n        lucene.log.active: 2015-02-06T17:00:28+0100 - 4.00 B\n        lucene.log.v0: 2015-02-01T17:39:30+0100 - 16.00 B\n        lucene.log.v1: 2015-02-02T02:28:48+0100 - 16.00 B\n        lucene.log.v2: 2015-02-02T02:29:26+0100 - 16.00 B\n        lucene.log.v3: 2015-02-06T01:41:41+0100 - 16.00 B\n        lucene.log.v4: 2015-02-06T01:41:44+0100 - 16.00 B\n      - Total: 2015-02-06T17:00:28+0100 - 140.00 B\n      lock: 2015-02-06T17:00:28+0100 - 0.00 B\n      messages.log: 2015-02-06T17:00:28+0100 - 145.86 kB\n      neostore: 2015-02-06T17:00:28+0100 - 81.00 B\n      neostore.id: 2015-02-06T17:00:28+0100 - 9.00 B\n      neostore.labeltokenstore.db: 2015-02-06T17:00:28+0100 - 0.00 B\n      neostore.labeltokenstore.db.id: 2015-02-06T17:00:28+0100 - 9.00 B\n      neostore.labeltokenstore.db.names: 2015-02-06T17:00:28+0100 - 38.00 B\n      neostore.labeltokenstore.db.names.id: 2015-02-06T17:00:28+0100 - 9.00 B\n      neostore.nodestore.db: 2015-02-06T17:00:28+0100 - 750.00 B\n      neostore.nodestore.db.id: 2015-02-06T17:00:28+0100 - 9.00 B\n      neostore.nodestore.db.labels: 2015-02-06T17:00:28+0100 - 68.00 B\n      neostore.nodestore.db.labels.id: 2015-02-06T17:00:28+0100 - 9.00 B\n      neostore.propertystore.db: 2015-02-06T17:00:28+0100 - 4.00 kB\n      neostore.propertystore.db.arrays: 2015-02-06T17:00:28+0100 - 128.00 B\n      neostore.propertystore.db.arrays.id: 2015-02-06T17:00:28+0100 - 9.00 B\n      neostore.propertystore.db.id: 2015-02-06T17:00:28+0100 - 9.00 B\n      neostore.propertystore.db.index: 2015-02-06T17:00:28+0100 - 54.00 B\n      neostore.propertystore.db.index.id: 2015-02-06T17:00:28+0100 - 9.00 B\n      neostore.propertystore.db.index.keys: 2015-02-06T17:00:28+0100 - 266.00 B\n      neostore.propertystore.db.index.keys.id: 2015-02-06T17:00:28+0100 - 9.00 B\n      neostore.propertystore.db.strings: 2015-02-06T17:00:28+0100 - 128.00 B\n      neostore.propertystore.db.strings.id: 2015-02-06T17:00:28+0100 - 9.00 B\n      neostore.relationshipgroupstore.db: 2015-02-06T17:00:28+0100 - 25.00 B\n      neostore.relationshipgroupstore.db.id: 2015-02-06T17:00:28+0100 - 9.00 B\n      neostore.relationshipstore.db: 2015-02-06T17:00:28+0100 - 1.66 kB\n      neostore.relationshipstore.db.id: 2015-02-06T17:00:28+0100 - 9.00 B\n      neostore.relationshiptypestore.db: 2015-02-06T17:00:28+0100 - 10.00 B\n      neostore.relationshiptypestore.db.id: 2015-02-06T17:00:28+0100 - 9.00 B\n      neostore.relationshiptypestore.db.names: 2015-02-06T17:00:28+0100 - 114.00 B\n      neostore.relationshiptypestore.db.names.id: 2015-02-06T17:00:28+0100 - 9.00 B\n      neostore.schemastore.db: 2015-02-06T17:00:28+0100 - 64.00 B\n      neostore.schemastore.db.id: 2015-02-06T17:00:28+0100 - 9.00 B\n      nioneo_logical.log.1: 2015-02-06T17:00:29+0100 - 16.00 B\n      nioneo_logical.log.active: 2015-02-06T17:00:28+0100 - 4.00 B\n      nioneo_logical.log.v0: 2015-02-01T17:39:30+0100 - 4.52 kB\n      nioneo_logical.log.v1: 2015-02-02T02:28:48+0100 - 3.34 kB\n      nioneo_logical.log.v2: 2015-02-02T02:29:26+0100 - 3.34 kB\n      nioneo_logical.log.v3: 2015-02-06T01:41:41+0100 - 3.34 kB\n      nioneo_logical.log.v4: 2015-02-06T01:41:44+0100 - 3.34 kB\n      schema:\n        label:\n          lucene:\n            segments.gen: 2015-02-01T17:39:30+0100 - 20.00 B\n            segments_1: 2015-02-01T17:39:30+0100 - 32.00 B\n            write.lock: 2015-02-06T17:00:28+0100 - 0.00 B\n          - Total: 2015-02-06T17:00:28+0100 - 52.00 B\n        - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      store_lock: 2015-02-01T17:39:29+0100 - 0.00 B\n      tm_tx_log.1: 2015-02-06T17:00:28+0100 - 0.00 B\n2015-02-06 16:00:29.003+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles END ---\n2015-02-06 16:00:29.050+0000 INFO  [org.neo4j]: Database is now ready\n2015-02-06 16:00:29.281+0000 INFO  [org.neo4j]: Shutdown started\n2015-02-06 16:00:29.281+0000 INFO  [org.neo4j]: Database is now unavailable\n2015-02-06 16:00:29.285+0000 INFO  [org.neo4j]: Closed log marathon/index/lucene.log\n2015-02-06 16:00:29.285+0000 INFO  [org.neo4j]: TM shutting down\n2015-02-06 16:00:29.293+0000 INFO  [org.neo4j]: Closed log marathon/nioneo_logical.log\n2015-02-06 16:00:29.293+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db.names hit=0 miss=4 switches=0 ooe=0\n2015-02-06 16:00:29.295+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db hit=0 miss=2 switches=0 ooe=0\n2015-02-06 16:00:29.295+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db.names hit=0 miss=0 switches=0 ooe=0\n2015-02-06 16:00:29.296+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-06 16:00:29.296+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.strings hit=0 miss=0 switches=0 ooe=0\n2015-02-06 16:00:29.297+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index.keys hit=0 miss=12 switches=0 ooe=0\n2015-02-06 16:00:29.297+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index hit=0 miss=6 switches=0 ooe=0\n2015-02-06 16:00:29.298+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.arrays hit=0 miss=0 switches=0 ooe=0\n2015-02-06 16:00:29.299+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db hit=20 miss=0 switches=0 ooe=0\n2015-02-06 16:00:29.300+0000 INFO  [org.neo4j]: marathon/neostore.relationshipstore.db hit=10 miss=0 switches=0 ooe=0\n2015-02-06 16:00:29.301+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db.labels hit=0 miss=0 switches=0 ooe=0\n2015-02-06 16:00:29.302+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db hit=10 miss=0 switches=0 ooe=0\n2015-02-06 16:00:29.302+0000 INFO  [org.neo4j]: marathon/neostore.schemastore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-06 16:00:29.303+0000 INFO  [org.neo4j]: marathon/neostore.relationshipgroupstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-06 16:00:29.304+0000 INFO  [org.neo4j]: marathon/neostore hit=0 miss=18 switches=0 ooe=0\n2015-02-06 16:00:29.305+0000 INFO  [org.neo4j]: NeoStore closed\n2015-02-06 16:00:29.305+0000 INFO  [org.neo4j]: --- STOPPING diagnostics START ---\n2015-02-06 16:00:29.305+0000 INFO  [org.neo4j]: --- STOPPING diagnostics END ---\n2015-02-06 16:00:30.398+0000 INFO  [org.neo4j]: No locking implementation specified, defaulting to 'community'\n2015-02-06 16:00:30.463+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics START ---\n2015-02-06 16:00:30.464+0000 INFO  [org.neo4j]: Neo4j Kernel properties:\n    neostore.propertystore.db.mapped_memory=1326M\n    neostore.nodestore.db.mapped_memory=368M\n    neostore.relationshipstore.db.mapped_memory=1624M\n    neostore.propertystore.db.strings.mapped_memory=1127M\n    store_dir=marathon\n    neostore.propertystore.db.arrays.mapped_memory=1277M\n    ephemeral=false\n2015-02-06 16:00:30.466+0000 INFO  [org.neo4j]: Diagnostics providers:\n    org.neo4j.kernel.configuration.Config\n    org.neo4j.kernel.info.DiagnosticsManager\n    SYSTEM_MEMORY\n    JAVA_MEMORY\n    OPERATING_SYSTEM\n    JAVA_VIRTUAL_MACHINE\n    CLASSPATH\n    LIBRARY_PATH\n    SYSTEM_PROPERTIES\n    NETWORK\n2015-02-06 16:00:30.467+0000 INFO  [org.neo4j]: System memory information:\n    Total Physical memory: 16.00 GB\n    Free Physical memory: 4.67 GB\n    Committed virtual memory: 6.81 GB\n    Total swap space: 2.00 GB\n    Free swap space: 1.60 GB\n2015-02-06 16:00:30.468+0000 INFO  [org.neo4j]: JVM memory information:\n    Free  memory: 173.98 MB\n    Total memory: 310.00 MB\n    Max   memory: 3.56 GB\n    Garbage Collector: PS Scavenge: [PS Eden Space, PS Survivor Space]\n    Garbage Collector: PS MarkSweep: [PS Eden Space, PS Survivor Space, PS Old Gen, PS Perm Gen]\n    Memory Pool: Code Cache (Non-heap memory): committed=4.00 MB, used=3.93 MB, max=48.00 MB, threshold=0.00 B\n    Memory Pool: PS Eden Space (Heap memory): committed=129.00 MB, used=103.74 MB, max=1.30 GB, threshold=?\n    Memory Pool: PS Survivor Space (Heap memory): committed=10.50 MB, used=10.48 MB, max=10.50 MB, threshold=?\n    Memory Pool: PS Old Gen (Heap memory): committed=170.50 MB, used=21.79 MB, max=2.67 GB, threshold=0.00 B\n    Memory Pool: PS Perm Gen (Non-heap memory): committed=33.50 MB, used=33.44 MB, max=82.00 MB, threshold=0.00 B\n2015-02-06 16:00:30.470+0000 INFO  [org.neo4j]: Operating system information:\n    Operating System: Mac OS X; version: 10.10.2; arch: x86_64; cpus: 8\n    Max number of file descriptors: 10240\n    Number of open file descriptors: 94\n    Process id: 6465@Dierk-Konigs-MacBook-Pro.local\n    Byte order: LITTLE_ENDIAN\n    Local timezone: Europe/Zurich\n2015-02-06 16:00:30.471+0000 INFO  [org.neo4j]: JVM information:\n    VM Name: Java HotSpot(TM) 64-Bit Server VM\n    VM Vendor: Oracle Corporation\n    VM Version: 24.51-b03\n    JIT compiler: HotSpot 64-Bit Tiered Compilers\n    VM Arguments: [-Dscript.name=/Users/dierkkoenig/.gvm/groovy/2.4.0/bin/groovy, -Dprogram.name=groovy, -Dgroovy.starter.conf=/Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf, -Dgroovy.home=/Users/dierkkoenig/.gvm/groovy/2.4.0, -Dtools.jar=/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar]\n2015-02-06 16:00:30.471+0000 INFO  [org.neo4j]: Java classpath:\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/qdox-1.12.1.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.parboiled/parboiled-scala_2.10/jars/parboiled-scala_2.10-1.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jcommander-1.47.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/bsf-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-configuration/commons-configuration/jars/commons-configuration-1.6.jar\n     [loader.3] file:/Users/dierkkoenig/Library/Java/Extensions/libJNPRAuthKit.jnilib\n     [loader.3] file:/System/Library/Java/Extensions/vecmath.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-groovysh-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-logging/commons-logging/jars/commons-logging-1.1.1.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-antlr-1.9.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/xmlpull-1.1.3.1.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunec.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3D.jnilib\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-lang/commons-lang/jars/commons-lang-2.4.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/localedata.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/charsets.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3daudio.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dcore.jar\n     [loader.3] file:/usr/lib/java/libjdns_sd.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-junit-1.9.4.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-management/jars/neo4j-management-2.1.6.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/zipfs.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.gremlin/gremlin-groovy/jars/gremlin-groovy-2.6.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/classes\n     [loader.3] file:/System/Library/Java/Extensions/jai_core.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ivy-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-json-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-templates-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.gremlin/gremlin-java/jars/gremlin-java-2.6.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/hamcrest-core-1.3.jar\n     [loader.3] file:/Library/Java/Extensions/RXTXcomm.jar\n     [loader.1] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.geronimo.specs/geronimo-jta_1.1_spec/jars/geronimo-jta_1.1_spec-1.1.1.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/dnsns.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/multiverse-core-0.7.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-commons/jars/neo4j-cypher-commons-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/junit-4.12.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-servlet-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/AppleScriptEngine.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/testng-6.8.13.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.parboiled/parboiled-core/jars/parboiled-core-1.1.6.jar\n     [loader.3] file:/System/Library/Java/Extensions/dns_sd.jar\n     [loader.2] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-1.9.4.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jce.jar\n     [loader.3] file:/System/Library/Java/Extensions/MRJToolkit.jar\n     [loader.3] file:/opt/subversion/lib/libsvnjavahl-1.0.0.0.dylib\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-beanutils/commons-beanutils/jars/commons-beanutils-1.7.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/sunrsasign.jar\n     [loader.3] file:/System/Library/Java/Extensions/libmlib_jai.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-bsf-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-nio-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/servlet-api-2.4.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-digester/commons-digester/jars/commons-digester-1.8.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-sql-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-xml-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jsp-api-2.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-compiler-2.0/jars/neo4j-cypher-compiler-2.0-2.0.4.jar\n     [loader.3] file:/System/Library/Java/Extensions/mlibwrapper_jai.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-primitive-collections/jars/neo4j-primitive-collections-2.1.6.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.lucene/lucene-core/jars/lucene-core-3.6.2.jar\n     [loader.3] file:/Library/Java/Extensions/librxtxSerial.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-ant-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher/jars/neo4j-cypher-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-test-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DAudio.jnilib\n     [loader.3] file:/System/Library/Java/Extensions/libAppleScriptEngine.jnilib\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jfr.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.scala-lang/scala-library/jars/scala-library-2.10.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-groovydoc-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-jmx-2.4.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DUtils.jnilib\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-kernel/jars/neo4j-kernel-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jansi-1.11.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/openbeans-1.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jsse.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jline-2.12.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dutils.jar\n     [loader.1] file:/projects/git/regina/listings/chap13/./\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-lucene-index/jars/neo4j-lucene-index-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.groovy/grapes/org.hsqldb/hsqldb/jars/hsqldb-2.3.2.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar\n     [loader.3] file:/System/Library/Java/Extensions/jai_codec.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-beanutils/commons-beanutils-core/jars/commons-beanutils-core-1.8.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-console-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.blueprints/blueprints-neo4j2-graph/jars/blueprints-neo4j2-graph-2.6.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/jsr166y-1.7.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.blueprints/blueprints-core/jars/blueprints-core-2.6.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-swing-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-compiler-2.1/jars/neo4j-cypher-compiler-2.1-2.1.6.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/resources.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/ant-launcher-1.9.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-docgenerator-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/commons-logging-1.2.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/rt.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/xstream-1.4.7.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/commons-cli-1.2.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-jsr223-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/groovy-testng-2.4.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-collections/commons-collections/jars/commons-collections-3.2.1.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop/pipes/jars/pipes-2.6.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.googlecode.concurrentlinkedhashmap/concurrentlinkedhashmap-lru/jars/concurrentlinkedhashmap-lru-1.4.1.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/2.4.0/lib/gpars-1.2.1.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-compiler-1.9/jars/neo4j-cypher-compiler-1.9-2.0.4.jar\n2015-02-06 16:00:30.475+0000 INFO  [org.neo4j]: Library path:\n    /Users/dierkkoenig/Library/Java/Extensions\n    /Library/Java/Extensions\n    /Network/Library/Java/Extensions\n    /System/Library/Java/Extensions\n    /usr/lib/java\n    /projects/git/regina/listings/chap13\n2015-02-06 16:00:30.475+0000 INFO  [org.neo4j]: System.properties:\n    sun.boot.library.path = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib\n    user.country.format = CH\n    gopherProxySet = false\n    path.separator = :\n    file.encoding.pkg = sun.io\n    user.country = DE\n    sun.java.launcher = SUN_STANDARD\n    sun.os.patch.level = unknown\n    program.name = groovy\n    user.dir = /projects/git/regina/listings/chap13\n    tools.jar = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n    sun.jnu.encoding = UTF-8\n    script.name = /Users/dierkkoenig/.gvm/groovy/2.4.0/bin/groovy\n    sun.management.compiler = HotSpot 64-Bit Tiered Compilers\n    http.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    user.home = /Users/dierkkoenig\n    user.timezone = Europe/Zurich\n    file.encoding = UTF-8\n    user.name = dierkkoenig\n    sun.java.command = org.codehaus.groovy.tools.GroovyStarter --main groovy.ui.GroovyMain --conf /Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf --classpath . ../../test\n    sun.arch.data.model = 64\n    user.language = de\n    awt.toolkit = sun.lwawt.macosx.LWCToolkit\n    file.separator = /\n    sun.io.unicode.encoding = UnicodeBig\n    sun.cpu.endian = little\n    groovy.starter.conf = /Users/dierkkoenig/.gvm/groovy/2.4.0/conf/groovy-starter.conf\n    socksNonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    ftp.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    groovy.home = /Users/dierkkoenig/.gvm/groovy/2.4.0\n    sun.cpu.isalist = \n2015-02-06 16:00:30.476+0000 INFO  [org.neo4j]: Network information:\n    Interface awdl0:\n        address: fe80:0:0:0:10c4:ecff:fed9:b394%8\n    Interface en0:\n        address: fe80:0:0:0:2acf:e9ff:fe19:ca6d%4\n        address: 10.0.1.19\n    Interface lo0:\n        address: fe80:0:0:0:0:0:0:1%1\n        address: 0:0:0:0:0:0:0:1\n        address: 127.0.0.1\n2015-02-06 16:00:30.476+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics END ---\n2015-02-06 16:00:30.522+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=114b)\n2015-02-06 16:00:30.523+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=10b)\n2015-02-06 16:00:30.523+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-02-06 16:00:30.524+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-02-06 16:00:30.524+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.strings] brickCount=0 brickSize=1181696b mappedMem=1181745152b (storeSize=128b)\n2015-02-06 16:00:30.524+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index.keys] brickCount=0 brickSize=0b mappedMem=0b (storeSize=266b)\n2015-02-06 16:00:30.525+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index] brickCount=0 brickSize=0b mappedMem=0b (storeSize=54b)\n2015-02-06 16:00:30.526+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.arrays] brickCount=0 brickSize=1339008b mappedMem=1339031552b (storeSize=128b)\n2015-02-06 16:00:30.542+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db] brickCount=0 brickSize=1390392b mappedMem=1390411776b (storeSize=4920b)\n2015-02-06 16:00:30.545+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipstore.db] brickCount=0 brickSize=1702856b mappedMem=1702887424b (storeSize=2040b)\n2015-02-06 16:00:30.545+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db.labels] brickCount=0 brickSize=0b mappedMem=0b (storeSize=68b)\n2015-02-06 16:00:30.547+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db] brickCount=0 brickSize=385875b mappedMem=385875968b (storeSize=900b)\n2015-02-06 16:00:30.548+0000 INFO  [org.neo4j]: [marathon/neostore.schemastore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=64b)\n2015-02-06 16:00:30.549+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipgroupstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=25b)\n2015-02-06 16:00:30.550+0000 INFO  [org.neo4j]: [marathon/neostore] brickCount=0 brickSize=0b mappedMem=0b (storeSize=81b)\n2015-02-06 16:00:30.722+0000 INFO  [org.neo4j]: Opened logical log [marathon/nioneo_logical.log.1] version=6, lastTxId=15 (clean)\n2015-02-06 16:00:30.731+0000 INFO  [org.neo4j]: TM opening log: marathon/tm_tx_log.1\n2015-02-06 16:00:30.736+0000 INFO  [org.neo4j]: Kernel health set to OK\n2015-02-06 16:00:30.743+0000 INFO  [org.neo4j]: Opened logical log [marathon/index/lucene.log.1] version=6, lastTxId=1 (clean)\n2015-02-06 16:00:30.746+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions START ---\n2015-02-06 16:00:30.746+0000 INFO  [org.neo4j]: Graph Database: org.neo4j.kernel.EmbeddedGraphDatabase StoreId{creationTime=1422808769411, randomId=1762119504651947014, storeVersion=14406081294923270, upgradeTime=1422808769411, upgradeId=1762119504651947014}\n2015-02-06 16:00:30.764+0000 INFO  [org.neo4j]: Kernel version: Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6\n2015-02-06 16:00:30.764+0000 INFO  [org.neo4j]: Neo4j component versions:\n2015-02-06 16:00:30.766+0000 INFO  [org.neo4j]:   Neo4j - Lucene Index (neo4j-lucene-index), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 16:00:30.766+0000 INFO  [org.neo4j]:   Neo4j - Cypher Compiler 2.1 (neo4j-cypher-compiler-2.1), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 16:00:30.766+0000 INFO  [org.neo4j]:   Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 16:00:30.766+0000 INFO  [org.neo4j]:   Neo4j - Cypher (neo4j-cypher), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 16:00:30.766+0000 INFO  [org.neo4j]:   Neo4j - Graph DB Monitoring and Management tools (neo4j-management), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 16:00:30.766+0000 INFO  [org.neo4j]:   Neo4j - Cypher Compiler 2.0 (neo4j-cypher-compiler-2.0), version: 2.0.4; revision: 2.0.4:2.0-maint:130/4a7d10bc274a5d26a180bbe9df25100e8a694748\n2015-02-06 16:00:30.766+0000 INFO  [org.neo4j]:   Neo4j - Cypher Compiler 1.9 (neo4j-cypher-compiler-1.9), version: 2.0.4; revision: 2.0.4:2.0-maint:130/4a7d10bc274a5d26a180bbe9df25100e8a694748\n2015-02-06 16:00:30.766+0000 INFO  [org.neo4j]:   Neo4j - Cypher Commons (neo4j-cypher-commons), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-02-06 16:00:30.766+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions END ---\n2015-02-06 16:00:30.768+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS START ---\n2015-02-06 16:00:30.768+0000 INFO  [org.neo4j]: Store versions:\n    Store versions:\n      NeoStore v0.A.3\n      SchemaStore v0.A.3\n      NodeStore v0.A.3\n      RelationshipStore v0.A.3\n      RelationshipTypeStore v0.A.3\n      LabelTokenStore v0.A.3\n      PropertyStore v0.A.3\n      PropertyIndexStore v0.A.3\n      StringPropertyStore v0.A.3\n      ArrayPropertyStore v0.A.3\n      RelationshipGroupStore v0.A.3\n2015-02-06 16:00:30.768+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS END ---\n2015-02-06 16:00:30.768+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE START ---\n2015-02-06 16:00:30.768+0000 INFO  [org.neo4j]: Id usage:\n    Id usage:\n      SchemaStore: used=1 high=0\n      NodeStore: used=60 high=59\n      RelationshipStore: used=60 high=59\n      RelationshipTypeStore: used=2 high=1\n      LabelTokenStore: used=0 high=-1\n      PropertyStore: used=120 high=119\n      PropertyIndexStore: used=6 high=5\n      StringPropertyStore: used=1 high=0\n      ArrayPropertyStore: used=1 high=0\n      RelationshipGroupStore: used=1 high=0\n2015-02-06 16:00:30.769+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE END ---\n2015-02-06 16:00:30.769+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS START ---\n2015-02-06 16:00:30.769+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS END ---\n2015-02-06 16:00:30.769+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles START ---\n2015-02-06 16:00:30.770+0000 INFO  [org.neo4j]: Disk space on partition (Total / Free / Free %): 499082485760 / 174966628352 / 35\nStorage files: (filename : modification date - size)\n      active_tx_log: 2015-02-01T17:39:29+0100 - 11.00 B\n      index:\n        lucene-store.db: 2015-02-06T17:00:29+0100 - 40.00 B\n        lucene.log.1: 2015-02-06T17:00:30+0100 - 16.00 B\n        lucene.log.active: 2015-02-06T17:00:30+0100 - 4.00 B\n        lucene.log.v0: 2015-02-01T17:39:30+0100 - 16.00 B\n        lucene.log.v1: 2015-02-02T02:28:48+0100 - 16.00 B\n        lucene.log.v2: 2015-02-02T02:29:26+0100 - 16.00 B\n        lucene.log.v3: 2015-02-06T01:41:41+0100 - 16.00 B\n        lucene.log.v4: 2015-02-06T01:41:44+0100 - 16.00 B\n        lucene.log.v5: 2015-02-06T17:00:29+0100 - 16.00 B\n      - Total: 2015-02-06T17:00:30+0100 - 156.00 B\n      lock: 2015-02-06T17:00:30+0100 - 0.00 B\n      messages.log: 2015-02-06T17:00:30+0100 - 173.24 kB\n      neostore: 2015-02-06T17:00:30+0100 - 81.00 B\n      neostore.id: 2015-02-06T17:00:30+0100 - 9.00 B\n      neostore.labeltokenstore.db: 2015-02-06T17:00:30+0100 - 0.00 B\n      neostore.labeltokenstore.db.id: 2015-02-06T17:00:30+0100 - 9.00 B\n      neostore.labeltokenstore.db.names: 2015-02-06T17:00:30+0100 - 38.00 B\n      neostore.labeltokenstore.db.names.id: 2015-02-06T17:00:30+0100 - 9.00 B\n      neostore.nodestore.db: 2015-02-06T17:00:30+0100 - 900.00 B\n      neostore.nodestore.db.id: 2015-02-06T17:00:30+0100 - 9.00 B\n      neostore.nodestore.db.labels: 2015-02-06T17:00:30+0100 - 68.00 B\n      neostore.nodestore.db.labels.id: 2015-02-06T17:00:30+0100 - 9.00 B\n      neostore.propertystore.db: 2015-02-06T17:00:30+0100 - 4.80 kB\n      neostore.propertystore.db.arrays: 2015-02-06T17:00:30+0100 - 128.00 B\n      neostore.propertystore.db.arrays.id: 2015-02-06T17:00:30+0100 - 9.00 B\n      neostore.propertystore.db.id: 2015-02-06T17:00:30+0100 - 9.00 B\n      neostore.propertystore.db.index: 2015-02-06T17:00:30+0100 - 54.00 B\n      neostore.propertystore.db.index.id: 2015-02-06T17:00:30+0100 - 9.00 B\n      neostore.propertystore.db.index.keys: 2015-02-06T17:00:30+0100 - 266.00 B\n      neostore.propertystore.db.index.keys.id: 2015-02-06T17:00:30+0100 - 9.00 B\n      neostore.propertystore.db.strings: 2015-02-06T17:00:30+0100 - 128.00 B\n      neostore.propertystore.db.strings.id: 2015-02-06T17:00:30+0100 - 9.00 B\n      neostore.relationshipgroupstore.db: 2015-02-06T17:00:30+0100 - 25.00 B\n      neostore.relationshipgroupstore.db.id: 2015-02-06T17:00:30+0100 - 9.00 B\n      neostore.relationshipstore.db: 2015-02-06T17:00:30+0100 - 1.99 kB\n      neostore.relationshipstore.db.id: 2015-02-06T17:00:30+0100 - 9.00 B\n      neostore.relationshiptypestore.db: 2015-02-06T17:00:30+0100 - 10.00 B\n      neostore.relationshiptypestore.db.id: 2015-02-06T17:00:30+0100 - 9.00 B\n      neostore.relationshiptypestore.db.names: 2015-02-06T17:00:30+0100 - 114.00 B\n      neostore.relationshiptypestore.db.names.id: 2015-02-06T17:00:30+0100 - 9.00 B\n      neostore.schemastore.db: 2015-02-06T17:00:30+0100 - 64.00 B\n      neostore.schemastore.db.id: 2015-02-06T17:00:30+0100 - 9.00 B\n      nioneo_logical.log.1: 2015-02-06T17:00:30+0100 - 16.00 B\n      nioneo_logical.log.active: 2015-02-06T17:00:30+0100 - 4.00 B\n      nioneo_logical.log.v0: 2015-02-01T17:39:30+0100 - 4.52 kB\n      nioneo_logical.log.v1: 2015-02-02T02:28:48+0100 - 3.34 kB\n      nioneo_logical.log.v2: 2015-02-02T02:29:26+0100 - 3.34 kB\n      nioneo_logical.log.v3: 2015-02-06T01:41:41+0100 - 3.34 kB\n      nioneo_logical.log.v4: 2015-02-06T01:41:44+0100 - 3.34 kB\n      nioneo_logical.log.v5: 2015-02-06T17:00:29+0100 - 3.34 kB\n      schema:\n        label:\n          lucene:\n            segments.gen: 2015-02-01T17:39:30+0100 - 20.00 B\n            segments_1: 2015-02-01T17:39:30+0100 - 32.00 B\n            write.lock: 2015-02-06T17:00:30+0100 - 0.00 B\n          - Total: 2015-02-06T17:00:30+0100 - 52.00 B\n        - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      store_lock: 2015-02-01T17:39:29+0100 - 0.00 B\n      tm_tx_log.1: 2015-02-06T17:00:30+0100 - 0.00 B\n2015-02-06 16:00:30.778+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles END ---\n2015-02-06 16:00:30.816+0000 INFO  [org.neo4j]: Database is now ready\n2015-02-06 16:00:32.050+0000 INFO  [org.neo4j]: Shutdown started\n2015-02-06 16:00:32.051+0000 INFO  [org.neo4j]: Database is now unavailable\n2015-02-06 16:00:32.054+0000 INFO  [org.neo4j]: Closed log marathon/index/lucene.log\n2015-02-06 16:00:32.055+0000 INFO  [org.neo4j]: TM shutting down\n2015-02-06 16:00:32.061+0000 INFO  [org.neo4j]: Closed log marathon/nioneo_logical.log\n2015-02-06 16:00:32.062+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db.names hit=0 miss=4 switches=0 ooe=0\n2015-02-06 16:00:32.063+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db hit=0 miss=2 switches=0 ooe=0\n2015-02-06 16:00:32.064+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db.names hit=0 miss=0 switches=0 ooe=0\n2015-02-06 16:00:32.064+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-06 16:00:32.065+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.strings hit=0 miss=0 switches=0 ooe=0\n2015-02-06 16:00:32.066+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index.keys hit=0 miss=12 switches=0 ooe=0\n2015-02-06 16:00:32.066+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index hit=0 miss=6 switches=0 ooe=0\n2015-02-06 16:00:32.067+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.arrays hit=0 miss=0 switches=0 ooe=0\n2015-02-06 16:00:32.068+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db hit=140 miss=0 switches=0 ooe=0\n2015-02-06 16:00:32.069+0000 INFO  [org.neo4j]: marathon/neostore.relationshipstore.db hit=82 miss=0 switches=0 ooe=0\n2015-02-06 16:00:32.070+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db.labels hit=0 miss=0 switches=0 ooe=0\n2015-02-06 16:00:32.071+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db hit=160 miss=0 switches=0 ooe=0\n2015-02-06 16:00:32.072+0000 INFO  [org.neo4j]: marathon/neostore.schemastore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-06 16:00:32.073+0000 INFO  [org.neo4j]: marathon/neostore.relationshipgroupstore.db hit=0 miss=0 switches=0 ooe=0\n2015-02-06 16:00:32.074+0000 INFO  [org.neo4j]: marathon/neostore hit=0 miss=18 switches=0 ooe=0\n2015-02-06 16:00:32.075+0000 INFO  [org.neo4j]: NeoStore closed\n2015-02-06 16:00:32.075+0000 INFO  [org.neo4j]: --- STOPPING diagnostics START ---\n2015-02-06 16:00:32.075+0000 INFO  [org.neo4j]: --- STOPPING diagnostics END ---\n2015-06-04 10:16:00.045+0000 INFO  [org.neo4j]: No locking implementation specified, defaulting to 'community'\n2015-06-04 10:16:00.147+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics START ---\n2015-06-04 10:16:00.149+0000 INFO  [org.neo4j]: Neo4j Kernel properties:\n    neostore.propertystore.db.mapped_memory=1326M\n    neostore.nodestore.db.mapped_memory=368M\n    neostore.relationshipstore.db.mapped_memory=1624M\n    neostore.propertystore.db.strings.mapped_memory=1127M\n    store_dir=marathon\n    neostore.propertystore.db.arrays.mapped_memory=1277M\n    ephemeral=false\n2015-06-04 10:16:00.152+0000 INFO  [org.neo4j]: Diagnostics providers:\n    org.neo4j.kernel.configuration.Config\n    org.neo4j.kernel.info.DiagnosticsManager\n    SYSTEM_MEMORY\n    JAVA_MEMORY\n    OPERATING_SYSTEM\n    JAVA_VIRTUAL_MACHINE\n    CLASSPATH\n    LIBRARY_PATH\n    SYSTEM_PROPERTIES\n    NETWORK\n2015-06-04 10:16:00.152+0000 INFO  [org.neo4j]: System memory information:\n    Total Physical memory: 16.00 GB\n    Free Physical memory: 6.71 GB\n    Committed virtual memory: 6.79 GB\n    Total swap space: 4.00 GB\n    Free swap space: 993.75 MB\n2015-06-04 10:16:00.157+0000 INFO  [org.neo4j]: JVM memory information:\n    Free  memory: 244.94 MB\n    Total memory: 310.00 MB\n    Max   memory: 3.56 GB\n    Garbage Collector: PS Scavenge: [PS Eden Space, PS Survivor Space]\n    Garbage Collector: PS MarkSweep: [PS Eden Space, PS Survivor Space, PS Old Gen, PS Perm Gen]\n    Memory Pool: Code Cache (Non-heap memory): committed=3.31 MB, used=3.26 MB, max=48.00 MB, threshold=0.00 B\n    Memory Pool: PS Eden Space (Heap memory): committed=129.00 MB, used=45.21 MB, max=1.31 GB, threshold=?\n    Memory Pool: PS Survivor Space (Heap memory): committed=10.50 MB, used=10.49 MB, max=10.50 MB, threshold=?\n    Memory Pool: PS Old Gen (Heap memory): committed=170.50 MB, used=11.87 MB, max=2.67 GB, threshold=0.00 B\n    Memory Pool: PS Perm Gen (Non-heap memory): committed=25.50 MB, used=25.18 MB, max=82.00 MB, threshold=0.00 B\n2015-06-04 10:16:00.164+0000 INFO  [org.neo4j]: Operating system information:\n    Operating System: Mac OS X; version: 10.10.3; arch: x86_64; cpus: 8\n    Max number of file descriptors: 10240\n    Number of open file descriptors: 78\n    Process id: 38491@Dierk-Konigs-MacBook-Pro.local\n    Byte order: LITTLE_ENDIAN\n    Local timezone: Europe/Zurich\n2015-06-04 10:16:00.167+0000 INFO  [org.neo4j]: JVM information:\n    VM Name: Java HotSpot(TM) 64-Bit Server VM\n    VM Vendor: Oracle Corporation\n    VM Version: 24.51-b03\n    JIT compiler: HotSpot 64-Bit Tiered Compilers\n    VM Arguments: [-Dscript.name=/Users/dierkkoenig/.gvm/groovy/current/bin/groovy, -Dprogram.name=groovy, -Dgroovy.starter.conf=/Users/dierkkoenig/.gvm/groovy/current/conf/groovy-starter.conf, -Dgroovy.home=/Users/dierkkoenig/.gvm/groovy/current, -Dtools.jar=/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar]\n2015-06-04 10:16:00.167+0000 INFO  [org.neo4j]: Java classpath:\n     [loader.3] file:/System/Library/Java/Extensions/dns_sd.jar\n     [loader.2] file:/Users/dierkkoenig/.gvm/groovy/2.4.3/lib/groovy-2.4.3.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jce.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-test-2.4.3.jar\n     [loader.3] file:/Users/dierkkoenig/Library/Java/Extensions/libJNPRAuthKit.jnilib\n     [loader.3] file:/System/Library/Java/Extensions/MRJToolkit.jar\n     [loader.3] file:/opt/subversion/lib/libsvnjavahl-1.0.0.0.dylib\n     [loader.3] file:/System/Library/Java/Extensions/vecmath.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/sunrsasign.jar\n     [loader.3] file:/System/Library/Java/Extensions/libmlib_jai.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/ant-launcher-1.9.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-xml-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-json-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-groovysh-2.4.3.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunec.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-bsf-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/jsp-api-2.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-docgenerator-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-servlet-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/ant-junit-1.9.4.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3D.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/jcommander-1.47.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-jsr223-2.4.3.jar\n     [loader.3] file:/System/Library/Java/Extensions/mlibwrapper_jai.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-primitive-collections/jars/neo4j-primitive-collections-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-testng-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/jline-2.12.jar\n     [classpath + loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-2.4.3.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.lucene/lucene-core/jars/lucene-core-3.6.2.jar\n     [loader.3] file:/Library/Java/Extensions/librxtxSerial.jnilib\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/localedata.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/charsets.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DAudio.jnilib\n     [loader.3] file:/System/Library/Java/Extensions/libAppleScriptEngine.jnilib\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jfr.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3daudio.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/multiverse-core-0.7.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DUtils.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/gpars-1.2.1.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-kernel/jars/neo4j-kernel-2.1.6.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dcore.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/servlet-api-2.4.jar\n     [loader.3] file:/usr/lib/java/libjdns_sd.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/commons-logging-1.2.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-templates-2.4.3.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jsse.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-console-2.4.3.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/zipfs.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dutils.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/classes\n     [loader.3] file:/System/Library/Java/Extensions/jai_core.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/xmlpull-1.1.3.1.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-lucene-index/jars/neo4j-lucene-index-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.groovy/grapes/org.hsqldb/hsqldb/jars/hsqldb-2.3.2.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/jansi-1.11.jar\n     [loader.3] file:/System/Library/Java/Extensions/jai_codec.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/ant-1.9.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/qdox-1.12.1.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/ivy-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/bsf-2.4.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/resources.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/jsr166y-1.7.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/junit-4.12.jar\n     [loader.3] file:/Library/Java/Extensions/RXTXcomm.jar\n     [loader.1] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/ant-antlr-1.9.4.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.geronimo.specs/geronimo-jta_1.1_spec/jars/geronimo-jta_1.1_spec-1.1.1.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/dnsns.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/rt.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/hamcrest-core-1.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-ant-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-groovydoc-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/openbeans-1.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-nio-2.4.3.jar\n     [loader.3] file:/System/Library/Java/Extensions/AppleScriptEngine.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/testng-6.8.13.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/xstream-1.4.7.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/commons-cli-1.2.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-sql-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-swing-2.4.3.jar\n     [loader.1] file:/projects/git/GroovyInAction/listings/chap13/./\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-jmx-2.4.3.jar\n2015-06-04 10:16:00.172+0000 INFO  [org.neo4j]: Library path:\n    /Users/dierkkoenig/Library/Java/Extensions\n    /Library/Java/Extensions\n    /Network/Library/Java/Extensions\n    /System/Library/Java/Extensions\n    /usr/lib/java\n    /projects/git/GroovyInAction/listings/chap13\n2015-06-04 10:16:00.172+0000 INFO  [org.neo4j]: System.properties:\n    sun.boot.library.path = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib\n    user.country.format = CH\n    gopherProxySet = false\n    path.separator = :\n    file.encoding.pkg = sun.io\n    user.country = DE\n    sun.java.launcher = SUN_STANDARD\n    sun.os.patch.level = unknown\n    program.name = groovy\n    user.dir = /projects/git/GroovyInAction/listings/chap13\n    tools.jar = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n    sun.jnu.encoding = UTF-8\n    script.name = /Users/dierkkoenig/.gvm/groovy/current/bin/groovy\n    sun.management.compiler = HotSpot 64-Bit Tiered Compilers\n    http.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    user.home = /Users/dierkkoenig\n    user.timezone = Europe/Zurich\n    file.encoding = UTF-8\n    user.name = dierkkoenig\n    sun.java.command = org.codehaus.groovy.tools.GroovyStarter --main groovy.ui.GroovyMain --conf /Users/dierkkoenig/.gvm/groovy/current/conf/groovy-starter.conf --classpath . ../../test\n    sun.arch.data.model = 64\n    user.language = de\n    awt.toolkit = sun.lwawt.macosx.LWCToolkit\n    file.separator = /\n    sun.io.unicode.encoding = UnicodeBig\n    sun.cpu.endian = little\n    groovy.starter.conf = /Users/dierkkoenig/.gvm/groovy/current/conf/groovy-starter.conf\n    socksNonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    ftp.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    groovy.home = /Users/dierkkoenig/.gvm/groovy/current\n    sun.cpu.isalist = \n2015-06-04 10:16:00.172+0000 INFO  [org.neo4j]: Network information:\n    Interface awdl0:\n        address: fe80:0:0:0:e42b:b3ff:fef6:4282%9\n    Interface en0:\n        address: fe80:0:0:0:2acf:e9ff:fe19:ca6d%4\n        address: 10.0.1.19\n    Interface lo0:\n        address: fe80:0:0:0:0:0:0:1%1\n        address: 0:0:0:0:0:0:0:1\n        address: 127.0.0.1\n2015-06-04 10:16:00.175+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics END ---\n2015-06-04 10:16:00.247+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=114b)\n2015-06-04 10:16:00.248+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=10b)\n2015-06-04 10:16:00.248+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-06-04 10:16:00.250+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-06-04 10:16:00.250+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.strings] brickCount=0 brickSize=1181696b mappedMem=1181745152b (storeSize=128b)\n2015-06-04 10:16:00.251+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index.keys] brickCount=0 brickSize=0b mappedMem=0b (storeSize=266b)\n2015-06-04 10:16:00.251+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index] brickCount=0 brickSize=0b mappedMem=0b (storeSize=54b)\n2015-06-04 10:16:00.252+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.arrays] brickCount=0 brickSize=1339008b mappedMem=1339031552b (storeSize=128b)\n2015-06-04 10:16:00.267+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db] brickCount=0 brickSize=1390392b mappedMem=1390411776b (storeSize=5740b)\n2015-06-04 10:16:00.270+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipstore.db] brickCount=0 brickSize=1702856b mappedMem=1702887424b (storeSize=2380b)\n2015-06-04 10:16:00.270+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db.labels] brickCount=0 brickSize=0b mappedMem=0b (storeSize=68b)\n2015-06-04 10:16:00.272+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db] brickCount=0 brickSize=385875b mappedMem=385875968b (storeSize=1050b)\n2015-06-04 10:16:00.273+0000 INFO  [org.neo4j]: [marathon/neostore.schemastore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=64b)\n2015-06-04 10:16:00.274+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipgroupstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=25b)\n2015-06-04 10:16:00.275+0000 INFO  [org.neo4j]: [marathon/neostore] brickCount=0 brickSize=0b mappedMem=0b (storeSize=81b)\n2015-06-04 10:16:00.529+0000 INFO  [org.neo4j]: Opened logical log [marathon/nioneo_logical.log.1] version=7, lastTxId=16 (clean)\n2015-06-04 10:16:00.534+0000 INFO  [org.neo4j]: TM opening log: marathon/tm_tx_log.1\n2015-06-04 10:16:00.540+0000 INFO  [org.neo4j]: Kernel health set to OK\n2015-06-04 10:16:00.551+0000 INFO  [org.neo4j]: Opened logical log [marathon/index/lucene.log.1] version=7, lastTxId=1 (clean)\n2015-06-04 10:16:00.555+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions START ---\n2015-06-04 10:16:00.555+0000 INFO  [org.neo4j]: Graph Database: org.neo4j.kernel.EmbeddedGraphDatabase StoreId{creationTime=1422808769411, randomId=1762119504651947014, storeVersion=14406081294923270, upgradeTime=1422808769411, upgradeId=1762119504651947014}\n2015-06-04 10:16:00.558+0000 INFO  [org.neo4j]: Kernel version: Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6\n2015-06-04 10:16:00.558+0000 INFO  [org.neo4j]: Neo4j component versions:\n2015-06-04 10:16:00.559+0000 INFO  [org.neo4j]:   Neo4j - Lucene Index (neo4j-lucene-index), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-06-04 10:16:00.559+0000 INFO  [org.neo4j]:   Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-06-04 10:16:00.559+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions END ---\n2015-06-04 10:16:00.561+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS START ---\n2015-06-04 10:16:00.562+0000 INFO  [org.neo4j]: Store versions:\n    Store versions:\n      NeoStore v0.A.3\n      SchemaStore v0.A.3\n      NodeStore v0.A.3\n      RelationshipStore v0.A.3\n      RelationshipTypeStore v0.A.3\n      LabelTokenStore v0.A.3\n      PropertyStore v0.A.3\n      PropertyIndexStore v0.A.3\n      StringPropertyStore v0.A.3\n      ArrayPropertyStore v0.A.3\n      RelationshipGroupStore v0.A.3\n2015-06-04 10:16:00.562+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS END ---\n2015-06-04 10:16:00.562+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE START ---\n2015-06-04 10:16:00.562+0000 INFO  [org.neo4j]: Id usage:\n    Id usage:\n      SchemaStore: used=1 high=0\n      NodeStore: used=70 high=69\n      RelationshipStore: used=70 high=69\n      RelationshipTypeStore: used=2 high=1\n      LabelTokenStore: used=0 high=-1\n      PropertyStore: used=140 high=139\n      PropertyIndexStore: used=6 high=5\n      StringPropertyStore: used=1 high=0\n      ArrayPropertyStore: used=1 high=0\n      RelationshipGroupStore: used=1 high=0\n2015-06-04 10:16:00.563+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE END ---\n2015-06-04 10:16:00.563+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS START ---\n2015-06-04 10:16:00.563+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS END ---\n2015-06-04 10:16:00.563+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles START ---\n2015-06-04 10:16:00.563+0000 INFO  [org.neo4j]: Disk space on partition (Total / Free / Free %): 499082485760 / 127505285120 / 25\nStorage files: (filename : modification date - size)\n      active_tx_log: 2015-02-01T17:39:29+0100 - 11.00 B\n      index:\n        lucene-store.db: 2015-02-06T17:00:32+0100 - 40.00 B\n        lucene.log.1: 2015-06-04T12:16:00+0200 - 16.00 B\n        lucene.log.active: 2015-06-04T12:16:00+0200 - 4.00 B\n        lucene.log.v0: 2015-02-01T17:39:30+0100 - 16.00 B\n        lucene.log.v1: 2015-02-02T02:28:48+0100 - 16.00 B\n        lucene.log.v2: 2015-02-02T02:29:26+0100 - 16.00 B\n        lucene.log.v3: 2015-02-06T01:41:41+0100 - 16.00 B\n        lucene.log.v4: 2015-02-06T01:41:44+0100 - 16.00 B\n        lucene.log.v5: 2015-02-06T17:00:29+0100 - 16.00 B\n        lucene.log.v6: 2015-02-06T17:00:32+0100 - 16.00 B\n      - Total: 2015-06-04T12:16:00+0200 - 172.00 B\n      lock: 2015-06-04T12:16:00+0200 - 0.00 B\n      messages.log: 2015-06-04T12:16:00+0200 - 197.17 kB\n      neostore: 2015-06-04T12:16:00+0200 - 81.00 B\n      neostore.id: 2015-06-04T12:16:00+0200 - 9.00 B\n      neostore.labeltokenstore.db: 2015-06-04T12:16:00+0200 - 0.00 B\n      neostore.labeltokenstore.db.id: 2015-06-04T12:16:00+0200 - 9.00 B\n      neostore.labeltokenstore.db.names: 2015-06-04T12:16:00+0200 - 38.00 B\n      neostore.labeltokenstore.db.names.id: 2015-06-04T12:16:00+0200 - 9.00 B\n      neostore.nodestore.db: 2015-06-04T12:16:00+0200 - 1.03 kB\n      neostore.nodestore.db.id: 2015-06-04T12:16:00+0200 - 9.00 B\n      neostore.nodestore.db.labels: 2015-06-04T12:16:00+0200 - 68.00 B\n      neostore.nodestore.db.labels.id: 2015-06-04T12:16:00+0200 - 9.00 B\n      neostore.propertystore.db: 2015-06-04T12:16:00+0200 - 5.61 kB\n      neostore.propertystore.db.arrays: 2015-06-04T12:16:00+0200 - 128.00 B\n      neostore.propertystore.db.arrays.id: 2015-06-04T12:16:00+0200 - 9.00 B\n      neostore.propertystore.db.id: 2015-06-04T12:16:00+0200 - 9.00 B\n      neostore.propertystore.db.index: 2015-06-04T12:16:00+0200 - 54.00 B\n      neostore.propertystore.db.index.id: 2015-06-04T12:16:00+0200 - 9.00 B\n      neostore.propertystore.db.index.keys: 2015-06-04T12:16:00+0200 - 266.00 B\n      neostore.propertystore.db.index.keys.id: 2015-06-04T12:16:00+0200 - 9.00 B\n      neostore.propertystore.db.strings: 2015-06-04T12:16:00+0200 - 128.00 B\n      neostore.propertystore.db.strings.id: 2015-06-04T12:16:00+0200 - 9.00 B\n      neostore.relationshipgroupstore.db: 2015-06-04T12:16:00+0200 - 25.00 B\n      neostore.relationshipgroupstore.db.id: 2015-06-04T12:16:00+0200 - 9.00 B\n      neostore.relationshipstore.db: 2015-06-04T12:16:00+0200 - 2.32 kB\n      neostore.relationshipstore.db.id: 2015-06-04T12:16:00+0200 - 9.00 B\n      neostore.relationshiptypestore.db: 2015-06-04T12:16:00+0200 - 10.00 B\n      neostore.relationshiptypestore.db.id: 2015-06-04T12:16:00+0200 - 9.00 B\n      neostore.relationshiptypestore.db.names: 2015-06-04T12:16:00+0200 - 114.00 B\n      neostore.relationshiptypestore.db.names.id: 2015-06-04T12:16:00+0200 - 9.00 B\n      neostore.schemastore.db: 2015-06-04T12:16:00+0200 - 64.00 B\n      neostore.schemastore.db.id: 2015-06-04T12:16:00+0200 - 9.00 B\n      nioneo_logical.log.1: 2015-06-04T12:16:00+0200 - 16.00 B\n      nioneo_logical.log.active: 2015-06-04T12:16:00+0200 - 4.00 B\n      nioneo_logical.log.v0: 2015-02-01T17:39:30+0100 - 4.52 kB\n      nioneo_logical.log.v1: 2015-02-02T02:28:48+0100 - 3.34 kB\n      nioneo_logical.log.v2: 2015-02-02T02:29:26+0100 - 3.34 kB\n      nioneo_logical.log.v3: 2015-02-06T01:41:41+0100 - 3.34 kB\n      nioneo_logical.log.v4: 2015-02-06T01:41:44+0100 - 3.34 kB\n      nioneo_logical.log.v5: 2015-02-06T17:00:29+0100 - 3.34 kB\n      nioneo_logical.log.v6: 2015-02-06T17:00:32+0100 - 3.34 kB\n      schema:\n        label:\n          lucene:\n            segments.gen: 2015-02-01T17:39:30+0100 - 20.00 B\n            segments_1: 2015-02-01T17:39:30+0100 - 32.00 B\n            write.lock: 2015-06-04T12:16:00+0200 - 0.00 B\n          - Total: 2015-06-04T12:16:00+0200 - 52.00 B\n        - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      store_lock: 2015-02-01T17:39:29+0100 - 0.00 B\n      tm_tx_log.1: 2015-06-04T12:16:00+0200 - 0.00 B\n2015-06-04 10:16:00.577+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles END ---\n2015-06-04 10:16:00.624+0000 INFO  [org.neo4j]: Database is now ready\n2015-06-04 10:16:00.866+0000 INFO  [org.neo4j]: Shutdown started\n2015-06-04 10:16:00.867+0000 INFO  [org.neo4j]: Database is now unavailable\n2015-06-04 10:16:00.870+0000 INFO  [org.neo4j]: Closed log marathon/index/lucene.log\n2015-06-04 10:16:00.870+0000 INFO  [org.neo4j]: TM shutting down\n2015-06-04 10:16:00.875+0000 INFO  [org.neo4j]: Closed log marathon/nioneo_logical.log\n2015-06-04 10:16:00.876+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db.names hit=0 miss=4 switches=0 ooe=0\n2015-06-04 10:16:00.877+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db hit=0 miss=2 switches=0 ooe=0\n2015-06-04 10:16:00.878+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db.names hit=0 miss=0 switches=0 ooe=0\n2015-06-04 10:16:00.878+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db hit=0 miss=0 switches=0 ooe=0\n2015-06-04 10:16:00.879+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.strings hit=0 miss=0 switches=0 ooe=0\n2015-06-04 10:16:00.880+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index.keys hit=0 miss=12 switches=0 ooe=0\n2015-06-04 10:16:00.880+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index hit=0 miss=6 switches=0 ooe=0\n2015-06-04 10:16:00.881+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.arrays hit=0 miss=0 switches=0 ooe=0\n2015-06-04 10:16:00.882+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db hit=20 miss=0 switches=0 ooe=0\n2015-06-04 10:16:00.883+0000 INFO  [org.neo4j]: marathon/neostore.relationshipstore.db hit=10 miss=0 switches=0 ooe=0\n2015-06-04 10:16:00.883+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db.labels hit=0 miss=0 switches=0 ooe=0\n2015-06-04 10:16:00.884+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db hit=10 miss=0 switches=0 ooe=0\n2015-06-04 10:16:00.885+0000 INFO  [org.neo4j]: marathon/neostore.schemastore.db hit=0 miss=0 switches=0 ooe=0\n2015-06-04 10:16:00.885+0000 INFO  [org.neo4j]: marathon/neostore.relationshipgroupstore.db hit=0 miss=0 switches=0 ooe=0\n2015-06-04 10:16:00.886+0000 INFO  [org.neo4j]: marathon/neostore hit=0 miss=18 switches=0 ooe=0\n2015-06-04 10:16:00.887+0000 INFO  [org.neo4j]: NeoStore closed\n2015-06-04 10:16:00.887+0000 INFO  [org.neo4j]: --- STOPPING diagnostics START ---\n2015-06-04 10:16:00.888+0000 INFO  [org.neo4j]: --- STOPPING diagnostics END ---\n2015-06-04 10:16:01.881+0000 INFO  [org.neo4j]: No locking implementation specified, defaulting to 'community'\n2015-06-04 10:16:01.946+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics START ---\n2015-06-04 10:16:01.947+0000 INFO  [org.neo4j]: Neo4j Kernel properties:\n    neostore.propertystore.db.mapped_memory=1326M\n    neostore.nodestore.db.mapped_memory=368M\n    neostore.relationshipstore.db.mapped_memory=1624M\n    neostore.propertystore.db.strings.mapped_memory=1127M\n    store_dir=marathon\n    neostore.propertystore.db.arrays.mapped_memory=1277M\n    ephemeral=false\n2015-06-04 10:16:01.949+0000 INFO  [org.neo4j]: Diagnostics providers:\n    org.neo4j.kernel.configuration.Config\n    org.neo4j.kernel.info.DiagnosticsManager\n    SYSTEM_MEMORY\n    JAVA_MEMORY\n    OPERATING_SYSTEM\n    JAVA_VIRTUAL_MACHINE\n    CLASSPATH\n    LIBRARY_PATH\n    SYSTEM_PROPERTIES\n    NETWORK\n2015-06-04 10:16:01.950+0000 INFO  [org.neo4j]: System memory information:\n    Total Physical memory: 16.00 GB\n    Free Physical memory: 6.62 GB\n    Committed virtual memory: 6.81 GB\n    Total swap space: 4.00 GB\n    Free swap space: 993.75 MB\n2015-06-04 10:16:01.951+0000 INFO  [org.neo4j]: JVM memory information:\n    Free  memory: 154.50 MB\n    Total memory: 310.00 MB\n    Max   memory: 3.56 GB\n    Garbage Collector: PS Scavenge: [PS Eden Space, PS Survivor Space]\n    Garbage Collector: PS MarkSweep: [PS Eden Space, PS Survivor Space, PS Old Gen, PS Perm Gen]\n    Memory Pool: Code Cache (Non-heap memory): committed=4.19 MB, used=4.08 MB, max=48.00 MB, threshold=0.00 B\n    Memory Pool: PS Eden Space (Heap memory): committed=129.00 MB, used=126.13 MB, max=1.30 GB, threshold=?\n    Memory Pool: PS Survivor Space (Heap memory): committed=10.50 MB, used=10.48 MB, max=10.50 MB, threshold=?\n    Memory Pool: PS Old Gen (Heap memory): committed=170.50 MB, used=21.41 MB, max=2.67 GB, threshold=0.00 B\n    Memory Pool: PS Perm Gen (Non-heap memory): committed=33.50 MB, used=33.47 MB, max=82.00 MB, threshold=0.00 B\n2015-06-04 10:16:01.953+0000 INFO  [org.neo4j]: Operating system information:\n    Operating System: Mac OS X; version: 10.10.3; arch: x86_64; cpus: 8\n    Max number of file descriptors: 10240\n    Number of open file descriptors: 101\n    Process id: 38491@Dierk-Konigs-MacBook-Pro.local\n    Byte order: LITTLE_ENDIAN\n    Local timezone: Europe/Zurich\n2015-06-04 10:16:01.953+0000 INFO  [org.neo4j]: JVM information:\n    VM Name: Java HotSpot(TM) 64-Bit Server VM\n    VM Vendor: Oracle Corporation\n    VM Version: 24.51-b03\n    JIT compiler: HotSpot 64-Bit Tiered Compilers\n    VM Arguments: [-Dscript.name=/Users/dierkkoenig/.gvm/groovy/current/bin/groovy, -Dprogram.name=groovy, -Dgroovy.starter.conf=/Users/dierkkoenig/.gvm/groovy/current/conf/groovy-starter.conf, -Dgroovy.home=/Users/dierkkoenig/.gvm/groovy/current, -Dtools.jar=/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar]\n2015-06-04 10:16:01.954+0000 INFO  [org.neo4j]: Java classpath:\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.parboiled/parboiled-scala_2.10/jars/parboiled-scala_2.10-1.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-test-2.4.3.jar\n     [loader.2] file:/Users/dierkkoenig/.gvm/groovy/2.4.3/lib/groovy-2.4.3.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-configuration/commons-configuration/jars/commons-configuration-1.6.jar\n     [loader.3] file:/Users/dierkkoenig/Library/Java/Extensions/libJNPRAuthKit.jnilib\n     [loader.3] file:/System/Library/Java/Extensions/vecmath.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-xml-2.4.3.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-logging/commons-logging/jars/commons-logging-1.1.1.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunec.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/jsp-api-2.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/ant-junit-1.9.4.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3D.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/jcommander-1.47.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-jsr223-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/jline-2.12.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-lang/commons-lang/jars/commons-lang-2.4.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/localedata.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/charsets.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3daudio.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dcore.jar\n     [loader.3] file:/usr/lib/java/libjdns_sd.jnilib\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-management/jars/neo4j-management-2.1.6.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/zipfs.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.gremlin/gremlin-groovy/jars/gremlin-groovy-2.6.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/classes\n     [loader.3] file:/System/Library/Java/Extensions/jai_core.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/xmlpull-1.1.3.1.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/jansi-1.11.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/ant-1.9.4.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.gremlin/gremlin-java/jars/gremlin-java-2.6.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/ivy-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/bsf-2.4.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/junit-4.12.jar\n     [loader.3] file:/Library/Java/Extensions/RXTXcomm.jar\n     [loader.1] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/ant-antlr-1.9.4.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.geronimo.specs/geronimo-jta_1.1_spec/jars/geronimo-jta_1.1_spec-1.1.1.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/dnsns.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/hamcrest-core-1.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-ant-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-groovydoc-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/openbeans-1.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-commons/jars/neo4j-cypher-commons-2.1.6.jar\n     [loader.3] file:/System/Library/Java/Extensions/AppleScriptEngine.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/testng-6.8.13.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/xstream-1.4.7.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-sql-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-swing-2.4.3.jar\n     [loader.1] file:/projects/git/GroovyInAction/listings/chap13/./\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.parboiled/parboiled-core/jars/parboiled-core-1.1.6.jar\n     [loader.3] file:/System/Library/Java/Extensions/dns_sd.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jce.jar\n     [loader.3] file:/System/Library/Java/Extensions/MRJToolkit.jar\n     [loader.3] file:/opt/subversion/lib/libsvnjavahl-1.0.0.0.dylib\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-beanutils/commons-beanutils/jars/commons-beanutils-1.7.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/sunrsasign.jar\n     [loader.3] file:/System/Library/Java/Extensions/libmlib_jai.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/ant-launcher-1.9.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-json-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-groovysh-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-bsf-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-docgenerator-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-servlet-2.4.3.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-digester/commons-digester/jars/commons-digester-1.8.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-compiler-2.0/jars/neo4j-cypher-compiler-2.0-2.0.4.jar\n     [loader.3] file:/System/Library/Java/Extensions/mlibwrapper_jai.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-primitive-collections/jars/neo4j-primitive-collections-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-testng-2.4.3.jar\n     [classpath + loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-2.4.3.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.apache.lucene/lucene-core/jars/lucene-core-3.6.2.jar\n     [loader.3] file:/Library/Java/Extensions/librxtxSerial.jnilib\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher/jars/neo4j-cypher-2.1.6.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DAudio.jnilib\n     [loader.3] file:/System/Library/Java/Extensions/libAppleScriptEngine.jnilib\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jfr.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.scala-lang/scala-library/jars/scala-library-2.10.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/multiverse-core-0.7.0.jar\n     [loader.3] file:/System/Library/Java/Extensions/libJ3DUtils.jnilib\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/gpars-1.2.1.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-kernel/jars/neo4j-kernel-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/servlet-api-2.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/commons-logging-1.2.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-templates-2.4.3.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-console-2.4.3.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/jsse.jar\n     [loader.3] file:/System/Library/Java/Extensions/j3dutils.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-lucene-index/jars/neo4j-lucene-index-2.1.6.jar\n     [loader.1] file:/Users/dierkkoenig/.groovy/grapes/org.hsqldb/hsqldb/jars/hsqldb-2.3.2.jar\n     [loader.3] file:/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar\n     [loader.3] file:/System/Library/Java/Extensions/jai_codec.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-beanutils/commons-beanutils-core/jars/commons-beanutils-core-1.8.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.blueprints/blueprints-neo4j2-graph/jars/blueprints-neo4j2-graph-2.6.0.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/qdox-1.12.1.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop.blueprints/blueprints-core/jars/blueprints-core-2.6.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-compiler-2.1/jars/neo4j-cypher-compiler-2.1-2.1.6.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/resources.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/jsr166y-1.7.0.jar\n     [bootstrap] /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/rt.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/commons-collections/commons-collections/jars/commons-collections-3.2.1.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-nio-2.4.3.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.tinkerpop/pipes/jars/pipes-2.6.0.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/com.googlecode.concurrentlinkedhashmap/concurrentlinkedhashmap-lru/jars/concurrentlinkedhashmap-lru-1.4.1.jar\n     [loader.0] file:/Users/dierkkoenig/.groovy/grapes/org.neo4j/neo4j-cypher-compiler-1.9/jars/neo4j-cypher-compiler-1.9-2.0.4.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/commons-cli-1.2.jar\n     [loader.1] file:/Users/dierkkoenig/.gvm/groovy/current/lib/groovy-jmx-2.4.3.jar\n2015-06-04 10:16:01.958+0000 INFO  [org.neo4j]: Library path:\n    /Users/dierkkoenig/Library/Java/Extensions\n    /Library/Java/Extensions\n    /Network/Library/Java/Extensions\n    /System/Library/Java/Extensions\n    /usr/lib/java\n    /projects/git/GroovyInAction/listings/chap13\n2015-06-04 10:16:01.958+0000 INFO  [org.neo4j]: System.properties:\n    sun.boot.library.path = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib\n    user.country.format = CH\n    gopherProxySet = false\n    path.separator = :\n    file.encoding.pkg = sun.io\n    user.country = DE\n    sun.java.launcher = SUN_STANDARD\n    sun.os.patch.level = unknown\n    program.name = groovy\n    user.dir = /projects/git/GroovyInAction/listings/chap13\n    tools.jar = /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/lib/tools.jar\n    sun.jnu.encoding = UTF-8\n    script.name = /Users/dierkkoenig/.gvm/groovy/current/bin/groovy\n    sun.management.compiler = HotSpot 64-Bit Tiered Compilers\n    http.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    user.home = /Users/dierkkoenig\n    user.timezone = Europe/Zurich\n    file.encoding = UTF-8\n    user.name = dierkkoenig\n    sun.java.command = org.codehaus.groovy.tools.GroovyStarter --main groovy.ui.GroovyMain --conf /Users/dierkkoenig/.gvm/groovy/current/conf/groovy-starter.conf --classpath . ../../test\n    sun.arch.data.model = 64\n    user.language = de\n    awt.toolkit = sun.lwawt.macosx.LWCToolkit\n    file.separator = /\n    sun.io.unicode.encoding = UnicodeBig\n    sun.cpu.endian = little\n    groovy.starter.conf = /Users/dierkkoenig/.gvm/groovy/current/conf/groovy-starter.conf\n    socksNonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    ftp.nonProxyHosts = local|*.local|169.254/16|*.169.254/16\n    groovy.home = /Users/dierkkoenig/.gvm/groovy/current\n    sun.cpu.isalist = \n2015-06-04 10:16:01.959+0000 INFO  [org.neo4j]: Network information:\n    Interface awdl0:\n        address: fe80:0:0:0:e42b:b3ff:fef6:4282%9\n    Interface en0:\n        address: fe80:0:0:0:2acf:e9ff:fe19:ca6d%4\n        address: 10.0.1.19\n    Interface lo0:\n        address: fe80:0:0:0:0:0:0:1%1\n        address: 0:0:0:0:0:0:0:1\n        address: 127.0.0.1\n2015-06-04 10:16:01.959+0000 INFO  [org.neo4j]: --- INITIALIZED diagnostics END ---\n2015-06-04 10:16:02.025+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=114b)\n2015-06-04 10:16:02.026+0000 INFO  [org.neo4j]: [marathon/neostore.relationshiptypestore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=10b)\n2015-06-04 10:16:02.027+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db.names] brickCount=0 brickSize=0b mappedMem=0b (storeSize=38b)\n2015-06-04 10:16:02.027+0000 INFO  [org.neo4j]: [marathon/neostore.labeltokenstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=0b)\n2015-06-04 10:16:02.028+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.strings] brickCount=0 brickSize=1181696b mappedMem=1181745152b (storeSize=128b)\n2015-06-04 10:16:02.028+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index.keys] brickCount=0 brickSize=0b mappedMem=0b (storeSize=266b)\n2015-06-04 10:16:02.028+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.index] brickCount=0 brickSize=0b mappedMem=0b (storeSize=54b)\n2015-06-04 10:16:02.029+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db.arrays] brickCount=0 brickSize=1339008b mappedMem=1339031552b (storeSize=128b)\n2015-06-04 10:16:02.045+0000 INFO  [org.neo4j]: [marathon/neostore.propertystore.db] brickCount=0 brickSize=1390392b mappedMem=1390411776b (storeSize=6560b)\n2015-06-04 10:16:02.047+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipstore.db] brickCount=0 brickSize=1702856b mappedMem=1702887424b (storeSize=2720b)\n2015-06-04 10:16:02.047+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db.labels] brickCount=0 brickSize=0b mappedMem=0b (storeSize=68b)\n2015-06-04 10:16:02.049+0000 INFO  [org.neo4j]: [marathon/neostore.nodestore.db] brickCount=0 brickSize=385875b mappedMem=385875968b (storeSize=1200b)\n2015-06-04 10:16:02.050+0000 INFO  [org.neo4j]: [marathon/neostore.schemastore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=64b)\n2015-06-04 10:16:02.054+0000 INFO  [org.neo4j]: [marathon/neostore.relationshipgroupstore.db] brickCount=0 brickSize=0b mappedMem=0b (storeSize=25b)\n2015-06-04 10:16:02.054+0000 INFO  [org.neo4j]: [marathon/neostore] brickCount=0 brickSize=0b mappedMem=0b (storeSize=81b)\n2015-06-04 10:16:02.194+0000 INFO  [org.neo4j]: Opened logical log [marathon/nioneo_logical.log.1] version=8, lastTxId=17 (clean)\n2015-06-04 10:16:02.202+0000 INFO  [org.neo4j]: TM opening log: marathon/tm_tx_log.1\n2015-06-04 10:16:02.206+0000 INFO  [org.neo4j]: Kernel health set to OK\n2015-06-04 10:16:02.213+0000 INFO  [org.neo4j]: Opened logical log [marathon/index/lucene.log.1] version=8, lastTxId=1 (clean)\n2015-06-04 10:16:02.217+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions START ---\n2015-06-04 10:16:02.217+0000 INFO  [org.neo4j]: Graph Database: org.neo4j.kernel.EmbeddedGraphDatabase StoreId{creationTime=1422808769411, randomId=1762119504651947014, storeVersion=14406081294923270, upgradeTime=1422808769411, upgradeId=1762119504651947014}\n2015-06-04 10:16:02.233+0000 INFO  [org.neo4j]: Kernel version: Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6\n2015-06-04 10:16:02.233+0000 INFO  [org.neo4j]: Neo4j component versions:\n2015-06-04 10:16:02.235+0000 INFO  [org.neo4j]:   Neo4j - Lucene Index (neo4j-lucene-index), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-06-04 10:16:02.235+0000 INFO  [org.neo4j]:   Neo4j - Cypher Compiler 2.1 (neo4j-cypher-compiler-2.1), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-06-04 10:16:02.235+0000 INFO  [org.neo4j]:   Neo4j - Graph Database Kernel (neo4j-kernel), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-06-04 10:16:02.235+0000 INFO  [org.neo4j]:   Neo4j - Cypher (neo4j-cypher), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-06-04 10:16:02.235+0000 INFO  [org.neo4j]:   Neo4j - Graph DB Monitoring and Management tools (neo4j-management), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-06-04 10:16:02.235+0000 INFO  [org.neo4j]:   Neo4j - Cypher Compiler 2.0 (neo4j-cypher-compiler-2.0), version: 2.0.4; revision: 2.0.4:2.0-maint:130/4a7d10bc274a5d26a180bbe9df25100e8a694748\n2015-06-04 10:16:02.235+0000 INFO  [org.neo4j]:   Neo4j - Cypher Compiler 1.9 (neo4j-cypher-compiler-1.9), version: 2.0.4; revision: 2.0.4:2.0-maint:130/4a7d10bc274a5d26a180bbe9df25100e8a694748\n2015-06-04 10:16:02.235+0000 INFO  [org.neo4j]:   Neo4j - Cypher Commons (neo4j-cypher-commons), version: 2.1.6; revision: 2.1.6:2.1-maint:605/0d7f25fc608f15c54ec1a01f4ba4564ebfb1071a\n2015-06-04 10:16:02.235+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:Versions END ---\n2015-06-04 10:16:02.237+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS START ---\n2015-06-04 10:16:02.237+0000 INFO  [org.neo4j]: Store versions:\n    Store versions:\n      NeoStore v0.A.3\n      SchemaStore v0.A.3\n      NodeStore v0.A.3\n      RelationshipStore v0.A.3\n      RelationshipTypeStore v0.A.3\n      LabelTokenStore v0.A.3\n      PropertyStore v0.A.3\n      PropertyIndexStore v0.A.3\n      StringPropertyStore v0.A.3\n      ArrayPropertyStore v0.A.3\n      RelationshipGroupStore v0.A.3\n2015-06-04 10:16:02.238+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_VERSIONS END ---\n2015-06-04 10:16:02.238+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE START ---\n2015-06-04 10:16:02.238+0000 INFO  [org.neo4j]: Id usage:\n    Id usage:\n      SchemaStore: used=1 high=0\n      NodeStore: used=80 high=79\n      RelationshipStore: used=80 high=79\n      RelationshipTypeStore: used=2 high=1\n      LabelTokenStore: used=0 high=-1\n      PropertyStore: used=160 high=159\n      PropertyIndexStore: used=6 high=5\n      StringPropertyStore: used=1 high=0\n      ArrayPropertyStore: used=1 high=0\n      RelationshipGroupStore: used=1 high=0\n2015-06-04 10:16:02.238+0000 INFO  [org.neo4j]: --- STARTED diagnostics for NEO_STORE_ID_USAGE END ---\n2015-06-04 10:16:02.238+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS START ---\n2015-06-04 10:16:02.238+0000 INFO  [org.neo4j]: --- STARTED diagnostics for PERSISTENCE_WINDOW_POOL_STATS END ---\n2015-06-04 10:16:02.239+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles START ---\n2015-06-04 10:16:02.239+0000 INFO  [org.neo4j]: Disk space on partition (Total / Free / Free %): 499082485760 / 127505190912 / 25\nStorage files: (filename : modification date - size)\n      active_tx_log: 2015-02-01T17:39:29+0100 - 11.00 B\n      index:\n        lucene-store.db: 2015-06-04T12:16:00+0200 - 40.00 B\n        lucene.log.1: 2015-06-04T12:16:02+0200 - 16.00 B\n        lucene.log.active: 2015-06-04T12:16:02+0200 - 4.00 B\n        lucene.log.v0: 2015-02-01T17:39:30+0100 - 16.00 B\n        lucene.log.v1: 2015-02-02T02:28:48+0100 - 16.00 B\n        lucene.log.v2: 2015-02-02T02:29:26+0100 - 16.00 B\n        lucene.log.v3: 2015-02-06T01:41:41+0100 - 16.00 B\n        lucene.log.v4: 2015-02-06T01:41:44+0100 - 16.00 B\n        lucene.log.v5: 2015-02-06T17:00:29+0100 - 16.00 B\n        lucene.log.v6: 2015-02-06T17:00:32+0100 - 16.00 B\n        lucene.log.v7: 2015-06-04T12:16:00+0200 - 16.00 B\n      - Total: 2015-06-04T12:16:02+0200 - 188.00 B\n      lock: 2015-06-04T12:16:02+0200 - 0.00 B\n      messages.log: 2015-06-04T12:16:02+0200 - 225.00 kB\n      neostore: 2015-06-04T12:16:02+0200 - 81.00 B\n      neostore.id: 2015-06-04T12:16:02+0200 - 9.00 B\n      neostore.labeltokenstore.db: 2015-06-04T12:16:02+0200 - 0.00 B\n      neostore.labeltokenstore.db.id: 2015-06-04T12:16:02+0200 - 9.00 B\n      neostore.labeltokenstore.db.names: 2015-06-04T12:16:02+0200 - 38.00 B\n      neostore.labeltokenstore.db.names.id: 2015-06-04T12:16:02+0200 - 9.00 B\n      neostore.nodestore.db: 2015-06-04T12:16:02+0200 - 1.17 kB\n      neostore.nodestore.db.id: 2015-06-04T12:16:02+0200 - 9.00 B\n      neostore.nodestore.db.labels: 2015-06-04T12:16:02+0200 - 68.00 B\n      neostore.nodestore.db.labels.id: 2015-06-04T12:16:02+0200 - 9.00 B\n      neostore.propertystore.db: 2015-06-04T12:16:02+0200 - 6.41 kB\n      neostore.propertystore.db.arrays: 2015-06-04T12:16:02+0200 - 128.00 B\n      neostore.propertystore.db.arrays.id: 2015-06-04T12:16:02+0200 - 9.00 B\n      neostore.propertystore.db.id: 2015-06-04T12:16:02+0200 - 9.00 B\n      neostore.propertystore.db.index: 2015-06-04T12:16:02+0200 - 54.00 B\n      neostore.propertystore.db.index.id: 2015-06-04T12:16:02+0200 - 9.00 B\n      neostore.propertystore.db.index.keys: 2015-06-04T12:16:02+0200 - 266.00 B\n      neostore.propertystore.db.index.keys.id: 2015-06-04T12:16:02+0200 - 9.00 B\n      neostore.propertystore.db.strings: 2015-06-04T12:16:02+0200 - 128.00 B\n      neostore.propertystore.db.strings.id: 2015-06-04T12:16:02+0200 - 9.00 B\n      neostore.relationshipgroupstore.db: 2015-06-04T12:16:02+0200 - 25.00 B\n      neostore.relationshipgroupstore.db.id: 2015-06-04T12:16:02+0200 - 9.00 B\n      neostore.relationshipstore.db: 2015-06-04T12:16:02+0200 - 2.66 kB\n      neostore.relationshipstore.db.id: 2015-06-04T12:16:02+0200 - 9.00 B\n      neostore.relationshiptypestore.db: 2015-06-04T12:16:02+0200 - 10.00 B\n      neostore.relationshiptypestore.db.id: 2015-06-04T12:16:02+0200 - 9.00 B\n      neostore.relationshiptypestore.db.names: 2015-06-04T12:16:02+0200 - 114.00 B\n      neostore.relationshiptypestore.db.names.id: 2015-06-04T12:16:02+0200 - 9.00 B\n      neostore.schemastore.db: 2015-06-04T12:16:02+0200 - 64.00 B\n      neostore.schemastore.db.id: 2015-06-04T12:16:02+0200 - 9.00 B\n      nioneo_logical.log.1: 2015-06-04T12:16:02+0200 - 16.00 B\n      nioneo_logical.log.active: 2015-06-04T12:16:02+0200 - 4.00 B\n      nioneo_logical.log.v6: 2015-02-06T17:00:32+0100 - 3.34 kB\n      nioneo_logical.log.v7: 2015-06-04T12:16:00+0200 - 3.34 kB\n      schema:\n        label:\n          lucene:\n            segments.gen: 2015-02-01T17:39:30+0100 - 20.00 B\n            segments_1: 2015-02-01T17:39:30+0100 - 32.00 B\n            write.lock: 2015-06-04T12:16:02+0200 - 0.00 B\n          - Total: 2015-06-04T12:16:02+0200 - 52.00 B\n        - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      - Total: 2015-02-01T17:39:29+0100 - 52.00 B\n      store_lock: 2015-02-01T17:39:29+0100 - 0.00 B\n      tm_tx_log.1: 2015-06-04T12:16:02+0200 - 0.00 B\n2015-06-04 10:16:02.247+0000 INFO  [org.neo4j]: --- STARTED diagnostics for KernelDiagnostics:StoreFiles END ---\n2015-06-04 10:16:02.288+0000 INFO  [org.neo4j]: Database is now ready\n2015-06-04 10:16:03.553+0000 INFO  [org.neo4j]: Shutdown started\n2015-06-04 10:16:03.554+0000 INFO  [org.neo4j]: Database is now unavailable\n2015-06-04 10:16:03.558+0000 INFO  [org.neo4j]: Closed log marathon/index/lucene.log\n2015-06-04 10:16:03.558+0000 INFO  [org.neo4j]: TM shutting down\n2015-06-04 10:16:03.564+0000 INFO  [org.neo4j]: Closed log marathon/nioneo_logical.log\n2015-06-04 10:16:03.565+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db.names hit=0 miss=4 switches=0 ooe=0\n2015-06-04 10:16:03.566+0000 INFO  [org.neo4j]: marathon/neostore.relationshiptypestore.db hit=0 miss=2 switches=0 ooe=0\n2015-06-04 10:16:03.566+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db.names hit=0 miss=0 switches=0 ooe=0\n2015-06-04 10:16:03.567+0000 INFO  [org.neo4j]: marathon/neostore.labeltokenstore.db hit=0 miss=0 switches=0 ooe=0\n2015-06-04 10:16:03.568+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.strings hit=0 miss=0 switches=0 ooe=0\n2015-06-04 10:16:03.569+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index.keys hit=0 miss=12 switches=0 ooe=0\n2015-06-04 10:16:03.569+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.index hit=0 miss=6 switches=0 ooe=0\n2015-06-04 10:16:03.570+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db.arrays hit=0 miss=0 switches=0 ooe=0\n2015-06-04 10:16:03.571+0000 INFO  [org.neo4j]: marathon/neostore.propertystore.db hit=180 miss=0 switches=0 ooe=0\n2015-06-04 10:16:03.572+0000 INFO  [org.neo4j]: marathon/neostore.relationshipstore.db hit=106 miss=0 switches=0 ooe=0\n2015-06-04 10:16:03.573+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db.labels hit=0 miss=0 switches=0 ooe=0\n2015-06-04 10:16:03.574+0000 INFO  [org.neo4j]: marathon/neostore.nodestore.db hit=210 miss=0 switches=0 ooe=0\n2015-06-04 10:16:03.574+0000 INFO  [org.neo4j]: marathon/neostore.schemastore.db hit=0 miss=0 switches=0 ooe=0\n2015-06-04 10:16:03.575+0000 INFO  [org.neo4j]: marathon/neostore.relationshipgroupstore.db hit=0 miss=0 switches=0 ooe=0\n2015-06-04 10:16:03.576+0000 INFO  [org.neo4j]: marathon/neostore hit=0 miss=18 switches=0 ooe=0\n2015-06-04 10:16:03.578+0000 INFO  [org.neo4j]: NeoStore closed\n2015-06-04 10:16:03.578+0000 INFO  [org.neo4j]: --- STOPPING diagnostics START ---\n2015-06-04 10:16:03.578+0000 INFO  [org.neo4j]: --- STOPPING diagnostics END ---\n"
  },
  {
    "path": "listings/chap13/marathon/store_lock",
    "content": ""
  },
  {
    "path": "listings/chap13/snippet1301_ConnectingWithGrab.groovy",
    "content": "@Grab('org.hsqldb:hsqldb:2.3.2')\n@GrabConfig(systemClassLoader=true)\nimport groovy.sql.Sql\n\ndef url = 'jdbc:hsqldb:mem:GinA'\ndef user = 'sa'\ndef password = ''\ndef driver = 'org.hsqldb.jdbcDriver'\ndef sql = Sql.newInstance(url, user, password, driver)\n\n// use 'sql' instance ...\n// optional test of a system table within HSQLDB\nassert sql.firstRow('SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS')[0] == 1\n\nsql.close()\n"
  },
  {
    "path": "listings/chap13/snippet1301_ConnectingWithInstance.groovy",
    "content": "import groovy.sql.Sql\n\ndef url = 'jdbc:hsqldb:mem:GinA'\ndef user = 'sa'\ndef password = ''\ndef driver = 'org.hsqldb.jdbcDriver'\n\nSql.withInstance(url, user, password, driver) { sql ->\n  // use 'sql' instance ...\n  // optional test of a system table within HSQLDB\n  assert sql.firstRow('SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS')[0] == 1\n}\n"
  },
  {
    "path": "listings/chap13/snippet1301_ConnectingWithMap.groovy",
    "content": "import groovy.sql.Sql\n\nimport static java.sql.ResultSet.CONCUR_READ_ONLY\n\n// ...\ndef sql = Sql.newInstance(\n    url: 'jdbc:hsqldb:mem:GinA',\n    user: 'sa',\n    password: '',\n    driver: 'org.hsqldb.jdbcDriver',\n    cacheStatements: true,\n    resultSetConcurrency: CONCUR_READ_ONLY)\n\n// use 'sql' instance ...\n\nsql.close()\n"
  },
  {
    "path": "listings/chap13/snippet1301_ReadEachRow.groovy",
    "content": "import util.DbUtil\nimport java.text.SimpleDateFormat\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\n\nprintln ' Athlete Info '.center(25, '-')\ndef fmt = new SimpleDateFormat('dd. MMM yyyy (E)', Locale.US)\nsql.eachRow('SELECT * FROM Athlete') { athlete ->\n  println athlete.firstname + ' ' + athlete.lastname\n  println 'born on ' + fmt.format(athlete.dateOfBirth)\n  println '-' * 25\n}\n\nsql.close()\n"
  },
  {
    "path": "listings/chap13/snippet1301_ReadEachRowList.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\n\nsql.eachRow('SELECT firstname, lastname FROM Athlete') { row ->\n  println row[0] + ' ' + row[1]\n}\n\nsql.close()\n"
  },
  {
    "path": "listings/chap13/snippet1301_ReadQuery.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\n\nsql.query('SELECT firstname, lastname FROM Athlete') { resultSet ->\n  if (resultSet.next()) {\n    print resultSet.getString(1)\n    print ' '\n    println resultSet.getString('lastname')\n  }\n}\n\nsql.close()\n"
  },
  {
    "path": "listings/chap13/snippet1301_ReadRows.groovy",
    "content": "import util.DbUtil\n\ndef sql = DbUtil.create()\nDbUtil.populate(sql)\n\nList athletes = sql.rows('SELECT firstname, lastname FROM Athlete')\nprintln \"There are ${athletes.size()} Athletes:\"\nprintln athletes.collect{\"${it[0]} ${it.lastname}\"}.join(\", \")\n\nsql.close()\n"
  },
  {
    "path": "listings/chap13/util/DbUtil.groovy",
    "content": "package util\n@Grab('org.hsqldb:hsqldb:2.3.2')\n@GrabConfig(systemClassLoader=true)\nimport groovy.sql.Sql\n\nimport java.util.logging.Level\nimport java.util.logging.Logger\n\nclass DbUtil {\n    static Sql create() {\n        def url = 'jdbc:hsqldb:mem:GinA'\n        def user = 'sa'\n        def password = ''\n        def driver = 'org.hsqldb.jdbcDriver'\n        def sql = Sql.newInstance(url, user, password, driver)\n\n        sql.execute \"\"\"\n            DROP TABLE Athlete IF EXISTS cascade;\n            DROP TABLE Record IF EXISTS;\n        \"\"\"\n\n        sql.execute \"\"\"\n            CREATE TABLE Athlete (\n              athleteId   INTEGER GENERATED BY DEFAULT AS IDENTITY,\n              firstname   VARCHAR(64),\n              lastname    VARCHAR(64),\n              dateOfBirth DATE,\n              UNIQUE(athleteId)\n            );\n        \"\"\"\n\n        sql.execute '''\nCREATE TABLE Record (\n  recordId    INTEGER GENERATED BY DEFAULT AS IDENTITY,\n  time        INTEGER,    -- in seconds\n  venue       VARCHAR(64),\n  whenRun     DATE,\n  fkAthlete   INTEGER,\n  CONSTRAINT fk FOREIGN KEY (fkAthlete)\n    REFERENCES Athlete (athleteId) ON DELETE CASCADE\n);\n        '''\n        sql\n    }\n\n    static void populate(sql) {\n        insertAthlete(sql, 'Paul', 'Tergat', '1969-06-17')\n        insertAthlete(sql, 'Khalid', 'Khannouchi', '1971-12-22')\n        insertAthlete(sql, 'Ronaldo', 'da Costa', '1970-06-07')\n        insertRecord(sql, 2, 4, 55, 'Berlin', '2003-09-28', 'Tergat')\n        insertRecord(sql, 2, 5, 38, 'London', '2002-04-14', 'Khannouchi')\n        insertRecord(sql, 2, 5, 42, 'Chicago', '1999-10-24', 'Khannouchi')\n        insertRecord(sql, 2, 6, 05, 'Berlin', '1998-09-20', 'da Costa')\n    }\n\n    static void insertAthlete(sql, first, last, dob) {\n        sql.execute \"\"\"\n            INSERT INTO Athlete (firstname, lastname, dateOfBirth)\n            VALUES (${first},${last},${dob})\n        \"\"\"\n    }\n\n    static void insertRecord(sql, h, m, s, venue, date, lastname) {\n        def time = h * 60 * 60 + m * 60 + s\n        sql.execute \"\"\"\n            INSERT INTO Record (time, venue, whenRun, fkAthlete)\n              SELECT $time, $venue, $date,\n                athleteId FROM Athlete WHERE lastname=$lastname\n        \"\"\"\n    }\n\n    // To enable logging, call the method below. You might also need\n    // to adjust the logging.properties file in JRE_HOME/lib to have:\n    // java.util.logging.ConsoleHandler.level = FINE\n    static void enableLogging() {\n        Logger.getLogger('groovy.sql').level = Level.FINE\n    }\n}\n"
  },
  {
    "path": "listings/chap13/util/MarathonRelationships.groovy",
    "content": "package util\n\n@Grab('org.neo4j:neo4j-kernel:2.1.6')\nimport org.neo4j.graphdb.*\n\nenum MarathonRelationships implements RelationshipType {\n  set, broke\n}\n"
  },
  {
    "path": "listings/chap13/util/Neo4jUtil.groovy",
    "content": "package util\n\n@Grab('org.neo4j:neo4j-kernel:2.1.6')\n@Grab('org.neo4j:neo4j-lucene-index:2.1.6;transitive=false')\n@Grab('org.apache.lucene:lucene-core:3.6.2')\nimport org.neo4j.graphdb.*\nimport org.neo4j.graphdb.factory.GraphDatabaseFactory\n\nclass Neo4jUtil {\n  static create() {                          //#A\n    def factory = new GraphDatabaseFactory()\n    def db = factory.newEmbeddedDatabase(\"marathon\")\n    addShutdownHook { db.shutdown() }\n\n    GraphDatabaseService.metaClass {\n      createNode { Map properties ->\n        def n = delegate.createNode()\n        properties.each { k, v -> n[k] = v }\n        n\n      }\n    }\n    Node.metaClass {\n      propertyMissing { String name, val ->\n        delegate.setProperty(name, val) }\n      propertyMissing { String name ->\n        delegate.getProperty(name) }\n      methodMissing { String name, args ->\n        delegate.createRelationshipTo(args[0],\n            MarathonRelationships.\"$name\")\n      }\n    }\n    Relationship.metaClass {\n      propertyMissing { String name, val ->\n        delegate.setProperty(name, val) }\n      propertyMissing { String name ->\n        delegate.getProperty(name) }\n    }\n    db\n  }\n\n  static insertAthlete(db, first, last, dob) {              //#B\n    db.createNode(first: first, last: last, dob: dob)\n  }\n\n  static insertRecord(db, h, m, s, venue, when, athlete) {  //#C\n    def secs = h * 60 * 60 + m * 60 + s\n    def record = db.createNode(time: secs, venue: venue, when: when)\n    athlete.set(record)\n    record\n  }\n}\n//#A Create database and turn on metaClass syntactic sugar\n//#B Utility method to create athlete\n//#C Utility method to create record\n"
  },
  {
    "path": "listings/chap14/Listing_14_01_Plan.txt",
    "content": "see: data/plan.xml"
  },
  {
    "path": "listings/chap14/Listing_14_02_DOM.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\nimport javax.xml.parsers.DocumentBuilderFactory\nimport static org.w3c.dom.Node.*\n\ndef factory = DocumentBuilderFactory.newInstance()\ndef builder = factory.newDocumentBuilder()\ndef doc     = builder.parse(new FileInputStream('data/plan.xml'))\ndef plan    = doc.documentElement\n\nString info(node) {\n  switch (node.nodeType) {\n    case ELEMENT_NODE:\n      return \"element: $node.nodeName\"\n    case ATTRIBUTE_NODE:\n      return \"attribute: $node.nodeName=$node.nodeValue\"\n    case TEXT_NODE:\n      return \"text: $node.nodeValue\"\n  }\n  return \"some other type: $node.nodeType\"\n}\n\nassert info(plan) == 'element: plan'\nassert plan.childNodes.length == 5                              //#1\n\n// what we'd have to do without groovy-xml DGM methods\n//def firstWeek = null\n//for (int i = 0; !firstWeek && i < plan.childNodes.length; i++) {\n//  if (plan.childNodes.item(i).nodeName == 'week')\n//    firstWeek = plan.childNodes.item(i)\n//}\n\ndef firstWeek = plan.childNodes.find { it.nodeName == 'week' }  //#2\nassert info(firstWeek) == 'element: week'\n\ndef firstWeekCapacity = firstWeek.attributes.getNamedItem('capacity')\nassert info(firstWeekCapacity) == 'attribute: capacity=8'\n\ndef firstTask = firstWeek.childNodes.item(1)                    //#3\nassert info(firstTask) == 'element: task'\n\ndef firstTaskText = firstTask.childNodes.item(0)\nassert info(firstTaskText) == 'text: easy'\n\ndef firstTaskTitle = firstTask.attributes.getNamedItem('title')\nassert info(firstTaskTitle) == 'attribute: title=read XML chapter'\n\ndef firstTaskTitleText = firstTaskTitle.childNodes.item(0)\nassert info(firstTaskTitleText) == 'text: read XML chapter'\n//#1 Element and whitespace children visible\n//#2 Object iteration method\n//#3 Indexed access\n"
  },
  {
    "path": "listings/chap14/Listing_14_03_DOM_Category.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\nimport groovy.xml.DOMBuilder\nimport groovy.xml.dom.DOMCategory\n\ndef doc = DOMBuilder.parse(new FileReader('data/plan.xml'))\ndef plan = doc.documentElement\n\nuse(DOMCategory) {\n  assert plan.name() == 'plan'                                  //|#1\n  assert plan.week[0].name() == 'week'                          //|#1\n  assert plan.week[0].'@capacity' == '8'                        // #2\n  assert plan.week.task[0].name() == 'task'\n  assert plan.week.task[0].text() == 'easy'                     // #3\n\n  // bonus material below here for comparative purposes with later examples\n  assert plan.week.task.size() == 5\n  assert plan.week.task.'@done'*.toInteger().sum() == 6\n  assert plan.week[1].task.every{ it.'@done' == '0' }\n\n// For legacy reasons, text nodes are regarded as children by\n// DOMCategory which yields slightly different code than for XmlParser\n// and XmlSlurper when using breadthFirst() and children() though\n// depthFirst() avoids these differences as it was introduced later\n  def elementNames = { it.nodeName.startsWith('#') ? [] : [it.name] }\n  assert plan.breadthFirst().iterator().collectMany(elementNames).join('->') ==\n      'plan->week->week->task->task->task->task->task'\n  assert plan.depthFirst()*.name().join('->') ==\n      'plan->week->task->task->task->week->task->task'\n  assert plan.'**'*.name().join('->') ==\n      'plan->week->task->task->task->week->task->task'\n}\n"
  },
  {
    "path": "listings/chap14/Listing_14_04_XmlParser.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\ndef plan = new XmlParser().parse(new File('data/plan.xml'))    // #1\n\nassert plan.name() == 'plan'\nassert plan.week[0].name() == 'week'\ndef firstTask = plan.week[0].task[0]                           // #2\nassert firstTask.name() == 'task'\nassert firstTask.text() == 'easy'\nassert firstTask.@title == 'read XML chapter'\n\n// bonus examples below here for comparison with other listings\nassert plan.children().size() == 2\n//def firstWeek = plan.children().find { it.name() == 'week' }\n//def firstWeek = plan.week[0]\nassert firstTask.'@title' == 'read XML chapter'\nassert plan.week.task.size() == 5\nassert plan.week.task.@done*.toInteger().sum() == 6\nassert plan.week[1].task.every{ it.@done == '0' }\n\nassert plan.breadthFirst()*.name().join('->') ==\n    'plan->week->week->task->task->task->task->task'\nassert plan.depthFirst()*.name().join('->') ==\n    'plan->week->task->task->task->week->task->task'\nassert plan.'**'*.name().join('->') ==\n    'plan->week->task->task->task->week->task->task'\n"
  },
  {
    "path": "listings/chap14/Listing_14_05_XmlSlurper.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\ndef plan = new XmlSlurper().parse(new File('data/plan.xml'))\n\nassert plan.week.task.size() == 5\nassert plan.week.task.@done*.toInteger().sum() == 6\nassert plan.week[1].task.every{ it.@done == '0' }\nassert plan.breadthFirst()*.name().join('->') ==\n    'plan->week->week->task->task->task->task->task'\nassert plan.depthFirst()*.name().join('->') ==\n    'plan->week->task->task->task->week->task->task'\nassert plan.depthFirst()*.name() == plan.'**'*.name()\n\n// bonus material below here for comparison with other listings\nassert plan.name() == 'plan'\nassert plan.children().size() == 2\n\ndef firstWeek = plan.children().find { it.name() == 'week' }\ndef firstTask = firstWeek.task[0]\nassert firstTask.name() == 'task'\nassert firstTask.text() == 'easy'\nassert firstTask.'@title' == 'read XML chapter'\n"
  },
  {
    "path": "listings/chap14/Listing_14_06_SAX.groovy",
    "content": "import javax.xml.parsers.SAXParserFactory\nimport org.xml.sax.*\nimport org.xml.sax.helpers.DefaultHandler\n\nclass PlanHandler extends DefaultHandler {                  //#1\n    def underway = []\n    def upcoming = []\n    void startElement(String namespace, String localName,\n            String qName, Attributes atts) {                //#2\n        if (qName != 'task') return                         //#3\n        def title = atts.getValue('title')\n        def total = atts.getValue('total')\n        switch (atts.getValue('done')) {\n            case '0'             : upcoming << title ; break\n            case { it != total } : underway << title ; break\n        }\n    }\n}\n\ndef handler = new PlanHandler()\ndef factory = SAXParserFactory.newInstance()\ndef reader = factory.newSAXParser().XMLReader               //#4\nreader.contentHandler = handler\nnew File('data/plan.xml').withInputStream { is ->\n    reader.parse(new InputSource(is))\n}\n\nassert handler.underway == [\n    'use in current project'\n]\nassert handler.upcoming == [\n    're-read DB chapter',\n    'use DB/XML combination'\n]"
  },
  {
    "path": "listings/chap14/Listing_14_07_StAX.groovy",
    "content": "// requires stax.jar and stax-api.jar for Java 1.5\nimport javax.xml.stream.*\n\ndef input = 'file:data/plan.xml'.toURL()\ndef underway = []\ndef upcoming = []\n\ndef eachStartElement(inputStream, Closure yield) {\n    def token = XMLInputFactory.newInstance()\n        .createXMLStreamReader(inputStream)               //#1\n    try {\n        while (token.hasNext()) {                         //#2\n            if (token.startElement) yield token\n            token.next()\n        }\n    } finally {\n        token?.close()\n        inputStream?.close()\n    }\n}\n\nclass XMLStreamCategory {                                 //|#3\n    static Object get(XMLStreamReader self, String key) { //|#3\n        return self.getAttributeValue(null, key)          //|#3\n    }                                                     //|#3\n}                                                         //|#3\n\nuse (XMLStreamCategory) {\n    eachStartElement(input.openStream()) { element ->\n        if (element.name.toString() != 'task') return\n        switch (element.done) {\n            case '0' :\n                upcoming << element.title\n                break\n            case { it != element.total } :\n                underway << element.title\n        }\n    }\n}\n\nassert underway == [\n    'use in current project'\n]\nassert upcoming == [\n    're-read DB chapter',\n    'use DB/XML combination'\n]\n"
  },
  {
    "path": "listings/chap14/Listing_14_08_XmlBoiler.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\nimport groovy.xml.MarkupBuilder\n\nvoid numberfy(Node node) {                           //#1\n  def atts = node.attributes()\n  atts.keySet().grep(['capacity', 'total', 'done']).each {\n    atts[it] = atts[it].toInteger()\n  }\n  node.each { if (it instanceof Node) numberfy(it) }\n}\n\nvoid taskStatus(task) {                              //#2\n  def atts = task.attributes()\n  switch (atts.done) {\n    case 0: atts.status = 'scheduled'; break\n    case 1..<atts.total: atts.status = 'in progress'; break\n    default: atts.status = 'finished';\n  }\n}\n\nvoid weekStatus(week) {                              //#3\n  week.task.each { taskStatus(it) }\n  def atts = week.attributes()\n  atts.status = 'scheduled'\n  if (week.task.every { it.@status == 'finished'})\n    atts.status = 'finished'\n  if (week.task.any { it.@status == 'in progress'})\n    atts.status = 'in progress'\n}\n\nvoid htmlReport(builder, plan) {                     //#4\n  builder.html {\n    head {\n      title('Current Groovy progress')\n      link(rel: 'stylesheet',\n          type: 'text/css',\n          href: 'style.css')\n    }\n    body {\n      plan.week.eachWithIndex { week, i ->\n        h1(\"Week No. $i: ${week.@status}\")\n        dl {\n          week.task.each { task ->\n            dt(class: task.@status, task.@title)\n            dd(\"(${task.@done}/${task.@total}): ${task.@status}\")\n} } } } } }\n\ndef node = new XmlParser().parse(new File('data/plan.xml'))\nnumberfy(node)                                       //#|5\nnode.week.each { weekStatus(it) }                    //#|5\n\nnew File('data/GroovyPlans.html').withWriter { writer ->\n  def builder = new MarkupBuilder(writer)\n  htmlReport(builder, node)\n}\n"
  },
  {
    "path": "listings/chap14/Listing_14_09_XmlStreamer.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\nimport groovy.xml.StreamingMarkupBuilder\n\ndef path = new XmlSlurper().parse(new File('data/plan.xml'))\n\ndef builder = new StreamingMarkupBuilder()\ndef copier = builder.bind{ mkp.yield(path) }\ndef result = \"$copier\"\n\nassert result.startsWith('<plan><week ')\nassert result.endsWith('</week></plan>')"
  },
  {
    "path": "listings/chap14/Listing_14_10_StreamedHtml.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\nimport groovy.xml.StreamingMarkupBuilder\n\ndef taskStatus(task) {                                       //#1\n  switch (task.@done.toInteger()) {\n    case 0: return 'scheduled'\n    case 1..<task.@total.toInteger(): return 'in progress'\n    default: return 'finished'\n  }\n}\n\ndef weekStatus(week) {                                       //#2\n  if (week.task.every { taskStatus(it) == 'finished' })\n    return 'finished'\n  if (week.task.any { taskStatus(it) == 'in progress' })\n    return 'in progress'\n  return 'scheduled'\n}\n\ndef plan = new XmlSlurper().parse(new File('data/plan.xml')) //#3\n\nClosure markup = {                                           //#4\n  html {\n    head {\n      title('Current Groovy progress')\n      link(rel: 'stylesheet',\n          type: 'text/css',\n          href: 'style.css')\n    }\n    body {\n      plan.week.eachWithIndex { week, i ->\n        h1(\"Week No. $i: ${owner.weekStatus(week)}\")\n        dl {\n          week.task.each { task ->\n            def status = owner.taskStatus(task)\n            dt(class: status, task.@title)\n            dd(\"(${task.@done}/${task.@total}): $status\")\n} } } } } }\n\ndef heater = new StreamingMarkupBuilder().bind(markup)       //#5\ndef outfile = new File('data/StreamedGroovyPlans.html')\noutfile.withWriter{ it << heater }                           //#6\n"
  },
  {
    "path": "listings/chap14/Listing_14_11_UpdateDomCategory.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\n\nimport groovy.xml.DOMBuilder\nimport groovy.xml.XmlUtil\nimport groovy.xml.dom.DOMCategory\n\ndef doc = DOMBuilder.parse(new FileReader('data/plan.xml'))\ndef plan = doc.documentElement\n\nuse(DOMCategory) {\n  plan.week[0].task[2]['@done'] = '2'                     // #1\n  plan.week[0].task[2].value = 'time saver'               // #2\n\n  plan.week[1].task[1].replaceNode {\n    task(done:'0', total:'4', title:'build web service')\n  }\n// an alternative to replace node is remove then append\n//  def oldTask = plan.week[1].task[1]\n//  plan.week[1].removeChild(oldTask)\n//  plan.week[1].appendNode('task', [done:'0', total:'4',\n//      title:'build web service'])\n\n//  plan.week[1].appendNode('task', [done:'0', total:'1',\n//      title:'build web service client'])\n    plan.week[1].task[1] + {\n      task(done:'0', total:'1', title:'build web service client')\n    }\n}\n\nUpdateChecker.check(XmlUtil.serialize(plan))\n"
  },
  {
    "path": "listings/chap14/Listing_14_12_UpdateParser.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\nimport groovy.xml.XmlUtil\n\ndef plan = new XmlParser().parse(new File('data/plan.xml'))\n\nplan.week[0].task[2].@done = '2'\nplan.week[0].task[2].value = 'time saver'\n\nplan.week[1].task[1].replaceNode {\n  task(done:'0', total:'4', title:'build web service')\n}\n//plan.week[1].appendNode('task', [done:'0', total:'1',\n//    title:'build web service client'])\nplan.week[1].task[1] + {\n  task(done:'0', total:'1', title:'build web service client')\n}\n\nUpdateChecker.check(XmlUtil.serialize(plan))\n"
  },
  {
    "path": "listings/chap14/Listing_14_13_UpdateSlurper.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\nimport groovy.xml.XmlUtil\n\ndef plan = new XmlSlurper().parse(new File('data/plan.xml'))\n\nplan.week[0].task[2].@done = '2'\nplan.week[0].task[2] = 'time saver'\n\nplan.week[1].task[1].replaceNode {\n  task(done:'0', total:'4', title:'build web service')\n}\n//plan.week[1].appendNode {\n//  task(done:'0', total:'1', title:'build web service client')\n//}\nplan.week[1].task[1] + {\n  task(done:'0', total:'1', title:'build web service client')\n}\n//plan.week[1] << {\n//  task(done:'0', total:'1', title:'build web service client')\n//}\n\nUpdateChecker.check(XmlUtil.serialize(plan))\n"
  },
  {
    "path": "listings/chap14/Listing_14_14_XPath.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\nimport groovy.xml.DOMBuilder\nimport groovy.xml.dom.DOMCategory\n\nimport javax.xml.xpath.XPathFactory\n\nimport static javax.xml.xpath.XPathConstants.NODESET\nimport static javax.xml.xpath.XPathConstants.NUMBER\n\ndef doc = DOMBuilder.parse(new FileReader('data/plan.xml'))\ndef plan = doc.documentElement\ndef xpath = XPathFactory.newInstance().newXPath()\n\ndef out = new StringBuilder()\nuse(DOMCategory) {                                             //#1\n  xpath.evaluate('//week', plan, NODESET).eachWithIndex {\n    wk, i ->                                                   //#2\n    out << \"\\nWeek No. $i\\n\"\n    int total = xpath.evaluate('sum(task/@total)', wk, NUMBER) //|#3\n    int done = xpath.evaluate('sum(task/@done)', wk, NUMBER)   //|#3\n    out << \" planned $total of ${wk.'@capacity'}\\n\"            //#4\n    out << \" done    $done of $total\"\n  }\n}\nassert out.toString() == '''\nWeek No. 0\n planned 7 of 8\n done    6 of 7\nWeek No. 1\n planned 4 of 8\n done    0 of 4'''\n"
  },
  {
    "path": "listings/chap14/Listing_14_15_GroovyPlansTemplate.txt",
    "content": "see: data/GroovyPlans.template.html"
  },
  {
    "path": "listings/chap14/Listing_14_16_XPathTemplate.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-templates:2.2.0')\nimport groovy.xml.DOMBuilder\nimport groovy.xml.dom.DOMCategory\nimport groovy.text.SimpleTemplateEngine as STE\n\nimport javax.xml.xpath.XPathFactory\nimport static javax.xml.xpath.XPathConstants.NODESET\nimport static javax.xml.xpath.XPathConstants.NUMBER\n\ndef doc  = DOMBuilder.parse(new FileReader('data/plan.xml'))\ndef plan = doc.documentElement\ndef xpath = XPathFactory.newInstance().newXPath()\n\ndef binding = [scale:1, weeks:[] ]\nuse(DOMCategory) {\n  xpath.evaluate('//week', plan, NODESET).each{ week ->     //#1\n    binding.weeks << [\n      total:   (int) xpath.evaluate('sum(task/@total)', week, NUMBER),\n      done:    (int) xpath.evaluate('sum(task/@done)', week, NUMBER),\n      capacity: week.'@capacity'.toInteger()\n    ]\n  }\n}\ndef max = binding.weeks.capacity.max()                      //#2\nif (max > 0) binding.scale = 200.intdiv(max)\n\ndef templateFile = new File('data/GroovyPlans.template.html')\ndef template     = new STE().createTemplate(templateFile)   //#3\n\nnew File('data/XPathGroovyPlans.html').withWriter {\n  it << template.make(binding)\n}"
  },
  {
    "path": "listings/chap14/Listing_14_17_JsonParser.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-json:2.2.0')\nimport groovy.json.JsonSlurper\n\n// add .newReader() to the file in Groovy versions prior to 2.2.0\ndef plan = new JsonSlurper().parse(new File('data/plan.json'))\nassert plan.weeks[0].tasks[0].status == 'easy'\nassert plan.weeks[1].capacity == 8\nassert plan.weeks[1].tasks[0].title == 're-read DB chapter'\n"
  },
  {
    "path": "listings/chap14/Listing_14_18_JsonBuilder.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-json:2.2.0')\nimport groovy.json.JsonBuilder\n\ndef builder = new JsonBuilder()\nbuilder.weeks {\n  capacity '8'\n  tasks(\n    [{\n      done '0'\n      total '4'\n      title 'build web service'\n    }, {\n      done '0'\n      total '1'\n      title 'build web service client'\n    }]\n  )\n}\n\nassert builder.toString() == '{\"weeks\":{\"capacity\":\"8\",\"tasks\":[' +\n    '{\"done\":\"0\",\"total\":\"4\",\"title\":\"build web service\"},' +\n    '{\"done\":\"0\",\"total\":\"1\",\"title\":\"build web service client\"}' +\n    ']}}'\n"
  },
  {
    "path": "listings/chap14/Listing_14_19_JsonBuilderLogic.groovy",
    "content": "import groovy.json.JsonBuilder\n\ndef builder = new JsonBuilder()\nbuilder {\n  invoices(1..3) { day ->                                       //#1\n    invoice(date: \"2015-01-0$day\") {                            //#2\n      item(count: day) {                                        //#2\n        product(name: 'ULC', dollar: 1499)                      //#2\n      }                                                         //#2\n    }                                                           //#2\n  }\n}\n\nassert builder.toPrettyString().startsWith(                     //#3\n'''{\n    \"invoices\": [\n        {\n            \"invoice\": [\n                {\n                    \"date\": \"2015-01-01\"\n''')\n//#1 Pretended method can take collection and Closure\n//#2 Closure defines JSON for each item in collection\n//#4 Check the start of pretty output"
  },
  {
    "path": "listings/chap14/Listing_14_20_JsonOutputAthlete.groovy",
    "content": "import static groovy.json.JsonOutput.*\n\ndef json = toJson([date: '2015-01-01', time: '6 am'])\nassert json == '{\"date\":\"2015-01-01\",\"time\":\"6 am\"}'\n\nclass Athlete { String first, last }\n\ndef mj = new Athlete(first: 'Michael', last: 'Jordan')\nassert toJson(mj) == '{\"first\":\"Michael\",\"last\":\"Jordan\"}'\n\ndef pt = new Athlete(first: 'Paul', last: 'Tergat')\ndef athletes = [basketball: mj, marathon: pt]\n\njson = toJson(athletes)\nassert prettyPrint(json) == '''\n{\n    \"basketball\": {\n        \"first\": \"Michael\",\n        \"last\": \"Jordan\"\n    },\n    \"marathon\": {\n        \"first\": \"Paul\",\n        \"last\": \"Tergat\"\n    }\n}\n'''.trim()\n"
  },
  {
    "path": "listings/chap14/UpdateChecker.groovy",
    "content": "class UpdateChecker {\n  static check(text) {\n    def updated = new XmlParser().parseText(text)\n    updated.week[0].with { w0 ->\n      assert w0.task.@done*.toInteger().sum() == 7\n      assert w0.find{ it.text() == 'time saver' }\n    }\n    updated.week[1].with { w1 ->\n      assert w1.children().size() == 3\n      assert w1.find{ it.@total == \"4\" }\n      assert w1.find{ it.@title == \"build web service client\" }\n      assert !w1.find{ it.@title == \"use DB/XML combination\" }\n    }\n  }\n}"
  },
  {
    "path": "listings/chap14/data/GroovyPlans.html",
    "content": "<html>\n  <head>\n    <title>Current Groovy progress</title>\n    <link rel='stylesheet' type='text/css' href='style.css' />\n  </head>\n  <body>\n    <h1>Week No. 0: in progress</h1>\n    <dl>\n      <dt class='finished'>read XML chapter</dt>\n      <dd>(2/2): finished</dd>\n      <dt class='finished'>try some reporting</dt>\n      <dd>(3/3): finished</dd>\n      <dt class='in progress'>use in current project</dt>\n      <dd>(1/2): in progress</dd>\n    </dl>\n    <h1>Week No. 1: scheduled</h1>\n    <dl>\n      <dt class='scheduled'>re-read DB chapter</dt>\n      <dd>(0/1): scheduled</dd>\n      <dt class='scheduled'>use DB/XML combination</dt>\n      <dd>(0/3): scheduled</dd>\n    </dl>\n  </body>\n</html>"
  },
  {
    "path": "listings/chap14/data/GroovyPlans.template.html",
    "content": "<html>\n  <head>\n    <title>Current Groovy progress</title>\n  </head>\n  <body>\n    <% weeks.eachWithIndex{ week, i -> %>\n    <h1>Week No. $i</h1>\n    <table cellspacing=\"5\" >\n        <tbody>\n            <% ['capacity','total','done'].each{ attr -> %>\n            <tr>\n\t            <td>$attr</td>\n\t            <td>${week[attr]}</td>\n                <td>\n                    <div style=\n\"border: thin solid #000000; width: ${week[attr]*scale}px\">\n                        &nbsp;</div>\n                </td>\n\t   \t    </tr>\n            <% } // end of attribute %>\n\t    </tbody>\n    </table>\n    <% } // end of week %>\n  </body>\n</html>"
  },
  {
    "path": "listings/chap14/data/StreamedGroovyPlans.html",
    "content": "<html><head><title>Current Groovy progress</title><link rel='stylesheet' type='text/css' href='style.css'/></head><body><h1>Week No. 0: in progress</h1><dl><dt class='finished'>read XML chapter</dt><dd>(2/2): finished</dd><dt class='finished'>try some reporting</dt><dd>(3/3): finished</dd><dt class='in progress'>use in current project</dt><dd>(1/2): in progress</dd></dl><h1>Week No. 1: scheduled</h1><dl><dt class='scheduled'>re-read DB chapter</dt><dd>(0/1): scheduled</dd><dt class='scheduled'>use DB/XML combination</dt><dd>(0/3): scheduled</dd></dl></body></html>"
  },
  {
    "path": "listings/chap14/data/XPathGroovyPlans.html",
    "content": "<html>\n  <head>\n    <title>Current Groovy progress</title>\n  </head>\n  <body>\n    \n    <h1>Week No. 0</h1>\n    <table cellspacing=\"5\" >\n        <tbody>\n            \n            <tr>\n\t            <td>capacity</td>\n\t            <td>8</td>\n                <td>\n                    <div style=\n\"border: thin solid #000000; width: 200px\">\n                        &nbsp;</div>\n                </td>\n\t   \t    </tr>\n            \n            <tr>\n\t            <td>total</td>\n\t            <td>7</td>\n                <td>\n                    <div style=\n\"border: thin solid #000000; width: 175px\">\n                        &nbsp;</div>\n                </td>\n\t   \t    </tr>\n            \n            <tr>\n\t            <td>done</td>\n\t            <td>6</td>\n                <td>\n                    <div style=\n\"border: thin solid #000000; width: 150px\">\n                        &nbsp;</div>\n                </td>\n\t   \t    </tr>\n            \n\t    </tbody>\n    </table>\n    \n    <h1>Week No. 1</h1>\n    <table cellspacing=\"5\" >\n        <tbody>\n            \n            <tr>\n\t            <td>capacity</td>\n\t            <td>8</td>\n                <td>\n                    <div style=\n\"border: thin solid #000000; width: 200px\">\n                        &nbsp;</div>\n                </td>\n\t   \t    </tr>\n            \n            <tr>\n\t            <td>total</td>\n\t            <td>4</td>\n                <td>\n                    <div style=\n\"border: thin solid #000000; width: 100px\">\n                        &nbsp;</div>\n                </td>\n\t   \t    </tr>\n            \n            <tr>\n\t            <td>done</td>\n\t            <td>0</td>\n                <td>\n                    <div style=\n\"border: thin solid #000000; width: 0px\">\n                        &nbsp;</div>\n                </td>\n\t   \t    </tr>\n            \n\t    </tbody>\n    </table>\n    \n  </body>\n</html>"
  },
  {
    "path": "listings/chap14/data/plan.json",
    "content": "{ \"weeks\": [\n  {\n    \"capacity\": 8,\n    \"tasks\": [\n      { \"done\": 2, \"total\": 2,\n        \"title\": \"read XML chapter\",   \"status\": \"easy\" },\n      { \"done\": 3, \"total\": 3,\n        \"title\": \"try some reporting\", \"status\": \"fun\" },\n      { \"done\": 1, \"total\": 2,\n        \"title\": \"use in current project\" }\n    ]\n  },\n  {\n    \"capacity\": 8,\n    \"tasks\": [\n      { \"done\": 0, \"total\": 1, \"title\": \"re-read DB chapter\" },\n      { \"done\": 0, \"total\": 3, \"title\": \"use DB/XML combination\" }\n    ]\n  }\n]}\n"
  },
  {
    "path": "listings/chap14/data/plan.xml",
    "content": "<plan>\n  <week capacity=\"8\">\n    <task done=\"2\" total=\"2\" title=\"read XML chapter\">easy</task>\n    <task done=\"3\" total=\"3\" title=\"try some reporting\">fun</task>\n    <task done=\"1\" total=\"2\" title=\"use in current project\"/>\n  </week>\n  <week capacity=\"8\">\n    <task done=\"0\" total=\"1\" title=\"re-read DB chapter\"/>\n    <task done=\"0\" total=\"3\" title=\"use DB/XML combination\"/>\n  </week>\n</plan>\n"
  },
  {
    "path": "listings/chap14/data/style.css",
    "content": "body {font-family:sans-serif;}\nh1 { font-size: large; }\ndl { padding-left: 10px}\ndt { font-weight:bold; }\ndt.finished { font-weight:normal; text-decoration:line-through; }\ndd {}"
  },
  {
    "path": "listings/chap14/log4j.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE log4j:configuration SYSTEM \"log4j.dtd\">\n\n<log4j:configuration xmlns:log4j=\"http://jakarta.apache.org/log4j/\" debug=\"false\">\n\t<appender name=\"console\" class=\"org.apache.log4j.ConsoleAppender\">\n\t\t<param name=\"Target\" value=\"System.out\" />\n\t\t<layout class=\"org.apache.log4j.PatternLayout\">\n\t\t\t<param name=\"ConversionPattern\" value=\"%d{ISO8601} %-5p  %c{1} - %m%n\" />\n\t\t</layout>\n\t</appender>\n\t\n\t<category name=\"groovyx.net.http\">\n\t\t<priority value=\"DEBUG\" />\n\t</category>\n\t\n\t<!-- Use DEBUG to see basic request/response info;  \n\t     Use TRACE to see headers for HttpURLClient. -->\n\t<category name=\"groovyx.net.http.HttpURLClient\">\n\t\t<priority value=\"INFO\" />\n\t</category>\n\n\t<category name=\"org.apache.http\">\n\t\t<priority value=\"INFO\" />\n\t</category>\n\t<category name=\"org.apache.http.headers\">\n\t\t<priority value=\"DEBUG\" />\n\t</category>\n\t<category name=\"org.apache.http.wire\">\n\t\t<priority value=\"DEBUG\" />\n\t</category>\n\t\n\t<root>\n\t\t<priority value=\"INFO\" />\n\t\t<appender-ref ref=\"console\" />\n\t</root>\n</log4j:configuration>\n"
  },
  {
    "path": "listings/chap15/Listing_15_01_RSS_bbcnews.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\ndef base = 'http://news.bbc.co.uk/rss/newsonline_uk_edition/'\ndef url = base + 'front_page/rss091.xml'\n\nprintln 'The top three news today:'\ndef items = new XmlParser().parse(url).channel[0].item\nfor (item in items[0..2]) {\n  println item.title.text()\n  println item.link.text()\n  println item.description.text()\n  println '----'\n}\n/*\nThe top three news today:\nThree Britons killed in balloon crash\nhttp://www.bbc.co.uk/news/uk-21588495...\nThree Britons are dead and another is in hospital...\n----\nEurope jitters over Italy deadlock\nhttp://www.bbc.co.uk/news/world-europe-21587123...\nEuropean politicians and markets react anxiously after Italy's general election...\n----\nRussia meteor's origin tracked down\nhttp://www.bbc.co.uk/news/science-environment-21579422...\nAstronomers trace origin of meteor that broke up over Russia earlier this month...\n----\n*/\n/*\n<rss version=\"2.0\" ...>\n  ...\n    <item>\n      <title>Three Britons killed in balloon crash</title>\n      <description>Three Britons are dead and another is in hospital...</description>\n      <link>http://www.bbc.co.uk/news/uk-21588495...</link>\n      <pubDate>Tue, 26 Feb 2013 13:20:07 GMT</pubDate>\n      ...\n    </item>\n...\n*/\n"
  },
  {
    "path": "listings/chap15/Listing_15_02_ATOM_devworks.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\nimport groovy.xml.Namespace\n\ndef url = 'http://www.ibm.com/developerworks/views/java/rss/' +\n    'libraryview.jsp?feed_by=atom'\ndef atom = new Namespace('http://www.w3.org/2005/Atom')\ndef numEntries = 3                                                  //#A\ndef entries = new XmlParser().parse(url)[atom.entry][0..<numEntries]\ndef len = \"dd mmm yyyy \".size()                                     //#B\ndef summaries = entries.collect {\n  it[atom.published].text()[0..<len] +\n      (it[atom.summary].text().contains('Groovy') ? '*' : ' ') +\n      it[atom.title].text()\n}\nprintln summaries.join(\"\\n\")\n//#A show latest 3 entries\n//#B chop published date after this many chars\n/*\n<feed xmlns=\"http://www.w3.org/2005/Atom\" xml:lang=\"en\">\n...\n  <entry>\n    <title>Java.next: The Java.next languages</title>\n    <summary>\n    A new developerWorks series by Neal Ford that performs a deep comparison\n    of three next-generation JVM languages: Groovy, Scala, and Clojure...\n    </summary>\n    <published>29 Jan 2013 05:00:00 +0000</published>\n    ...\n  </entry>\n...\n */\n/*\n26 Feb 2013  Test automation and continuous integration with STAF/STAX\n05 Feb 2013  HTML5 2D game development: Manipulating time, Part 1\n29 Jan 2013 *Java.next: The Java.next languages\n29 Jan 2013  Functional thinking: Why functional programming is on the rise\n15 Jan 2013  Look-ahead Java deserialization\n08 Jan 2013  HTML5 2D game development: Implementing Sprite behaviors\n08 Jan 2013  Agile DevOps: Continuous software delivery in the cloud\n19 Dec 2012 *Functional thinking: Laziness, Part 2\n*/\n"
  },
  {
    "path": "listings/chap15/Listing_15_03_REST_jira_url.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\n//@Grab('org.codehaus.groovy:groovy-json:2.2.0')\nimport groovy.json.JsonSlurper\n\nclass Jira {\n  def base = 'https://issues.apache.org/jira/rest/api/latest/issue/'\n  def slurper = new JsonSlurper()\n\n  def query(key) {\n    def httpConnection = new URL(base + key).openConnection()\n    assert httpConnection.responseCode == httpConnection.HTTP_OK\n    slurper.parse(httpConnection.inputStream.newReader())\n  }\n}\n\ndef jira = new Jira()\ndef response = jira.query(\"GROOVY-5999\")\nresponse.fields.with {\n  assert summary == \"Make @Delegate work with @DelegatesTo\"\n  assert fixVersions.name == ['2.1.1']\n  assert resolutiondate.startsWith('2013-02-14')\n}\n"
  },
  {
    "path": "listings/chap15/Listing_15_04_REST_jira_httpb_get.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\n//@Grab('org.codehaus.groovy:groovy-json:2.2.0')\n@Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7.2')\nimport groovyx.net.http.RESTClient\n\ndef base = 'https://issues.apache.org/jira/rest/api/latest/'\ndef jira = new RESTClient(base)\njira.get(path: 'issue/GROOVY-5999') { resp, json ->\n  assert resp.status == 200\n  json.fields.with {\n    assert summary == \"Make @Delegate work with @DelegatesTo\"\n    assert fixVersions.name == ['2.1.1']\n    assert resolutiondate.startsWith('2013-02-14')\n  }\n}\n"
  },
  {
    "path": "listings/chap15/Listing_15_05_REST_currency_httpb_get.groovy",
    "content": "@Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7.2')\nimport groovyx.net.http.RESTClient\n\ndef url = 'http://www.webservicex.net/CurrencyConvertor.asmx/'\ndef converter = new RESTClient(url)\ndef params = [FromCurrency: 'USD', ToCurrency: 'EUR']\nconverter.get(path: 'ConversionRate', query: params) { resp, data ->\n  assert resp.status == 200\n  assert data.name() == 'double'\n  println data.text()\n}\n// => http://www.webservicex.net/CurrencyConvertor.asmx/ConversionRate?FromCurrency=USD&ToCurrency=EUR\n// => <double xmlns=\"http://www.webserviceX.NET/\">0.882</double>\n// => 0.882\n\n// Apparently webservicex.net is having issues with their currency converter. Expect a ConversionRate of \"-1\".\n"
  },
  {
    "path": "listings/chap15/Listing_15_06_REST_currency_httpb_post.groovy",
    "content": "@Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7.2')\nimport groovyx.net.http.RESTClient\nimport static groovyx.net.http.ContentType.URLENC\n\ndef url = 'http://www.webservicex.net/CurrencyConvertor.asmx/'\ndef converter = new RESTClient(url)\ndef postBody = [FromCurrency: 'USD', ToCurrency: 'EUR']\nconverter.post(path: 'ConversionRate', body: postBody,\n    requestContentType: URLENC) { resp, data ->\n  assert resp.status == 200\n  assert data.name() == 'double'\n  println data.text()\n}\n// => http://www.webservicex.net/CurrencyConvertor.asmx/ConversionRate\n// => <double xmlns=\"http://www.webserviceX.NET/\">0.882</double>\n// => 0.882\n"
  },
  {
    "path": "listings/chap15/Listing_15_07_REST_currency_jaxrs.groovy",
    "content": "@Grab('org.jboss.resteasy:resteasy-client:3.0.10.Final')\nimport javax.ws.rs.client.ClientBuilder\n\ndef client = ClientBuilder.newClient()\ndef base = \"http://www.webservicex.net/CurrencyConvertor.asmx\"\ndef response = client.target(base + '/ConversionRate')\n    .queryParam(\"FromCurrency\", \"USD\")\n    .queryParam(\"ToCurrency\", \"EUR\")\n    .request().get(String)                             //#1\ndef rate = new XmlSlurper().parseText(response)\nassert rate.name() == 'double'\nprintln rate.text()\n//#1 specify a String response\n\n// => 0.882\n"
  },
  {
    "path": "listings/chap15/Listing_15_08_REST_currency_jaxrs_proxy.groovy",
    "content": "@Grab('org.jboss.resteasy:resteasy-client:3.0.10.Final')\nimport javax.ws.rs.GET\nimport javax.ws.rs.Path\nimport javax.ws.rs.Produces\nimport javax.ws.rs.QueryParam\nimport javax.ws.rs.client.ClientBuilder\n\ninterface CurrencyConvertor {\n  @GET\n  @Path(\"ConversionRate\")\n  @Produces(\"application/xml\")\n  String convert(@QueryParam(\"FromCurrency\") String from,\n                 @QueryParam(\"ToCurrency\") String to)\n}\n\ndef client = ClientBuilder.newClient()\ndef base = \"http://www.webservicex.net/CurrencyConvertor.asmx\"\ndef proxy = client.target(base).proxy(CurrencyConvertor)\ndef response = proxy.convert(\"USD\", \"EUR\")\ndef root = new XmlSlurper().parseText(response)\nassert root.name() == 'double'\nprintln root.text()\n\n// => 0.882\n"
  },
  {
    "path": "listings/chap15/Listing_15_09_XMLRPC_echo.groovy",
    "content": "@Grab('org.codehaus.groovy:groovy-xmlrpc:0.8')\nimport groovy.net.xmlrpc.XMLRPCServerProxy as Proxy\nimport groovy.net.xmlrpc.XMLRPCServer as Server\n\ndef server = new Server()\nserver.echo = { return it }\n\ndef socket = new ServerSocket(8080)\nserver.startServer(socket)\n\nremote = new Proxy(\"http://localhost:8080/\")             //|#A\nassert 'Hello world!' == remote.echo('Hello world!')     //|#A\n\nserver.stopServer()\n//#A Client code\n"
  },
  {
    "path": "listings/chap15/Listing_15_10_XMLRPC_jira.groovy",
    "content": "@Grab('org.codehaus.groovy:groovy-xmlrpc:0.8')\nimport groovy.net.xmlrpc.XMLRPCServerProxy as Proxy\n\nclass JiraProxy extends Proxy {\n  JiraProxy(url) { super(url) }\n\n  Object invokeMethod(String methodname, args) {\n    super.invokeMethod('jira1.' + methodname, args)\n  }\n}\n\ndef jira = new JiraProxy('https://issues.apache.org/jira/rpc/xmlrpc')\n\n// insert your ASF username and password below\njira.login('username', '****') { loginToken ->\n  def projects = getProjectsNoSchemes(loginToken)\n  println \"${projects.size()} projects found in the Apache jira\"\n  def groovy = projects.find { it.name == 'Groovy' }\n  if (groovy) {\n    println \"Found the $groovy.name project with key $groovy.key\"\n    println \"Description: $groovy.description\"\n    println \"Led by $groovy.lead and hosted at $groovy.projectUrl\"\n  }\n}\n\n/*\n519 projects found in the Apache jira\nFound the groovy project with key GROOVY\nDescription: Groovy programming language: a modern dynamic language for the JVM\nLed by guillaume and hosted at https://groovy.incubator.apache.org/\n*/"
  },
  {
    "path": "listings/chap15/Listing_15_11_SOAP_wsdl.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-xml:2.2.0')\nimport groovy.xml.Namespace\n\ndef url  = 'http://www.webservicex.net/CurrencyConvertor.asmx?WSDL'\ndef wsdl = new Namespace('http://schemas.xmlsoap.org/wsdl/','wsdl')\ndef doc  = new XmlParser().parse(url)\n\nprintln doc[wsdl.portType][wsdl.operation].'@name'\n\n// -> [ConversionRate, ConversionRate, ConversionRate]"
  },
  {
    "path": "listings/chap15/Listing_15_12_SOAP11_currency_url.groovy",
    "content": "//@Grab('org.codehaus.groovy:groovy-templates:2.2.0')\nimport groovy.text.SimpleTemplateEngine as STE\nimport groovy.xml.Namespace\n\ndef file     = new File('data/conv.templ.xml')                 //#A\ndef template = new STE().createTemplate(file)\ndef params   = [from:'USD', to:'EUR']\ndef request  = template.make(params).toString().getBytes('UTF-8')\n\ndef url  = 'http://www.webservicex.net/CurrencyConvertor.asmx'\ndef conn = new URL(url).openConnection()\ndef reqProps = [\n  'Content-Type': 'text/xml; charset=UTF-8',                   //#|B\n  'SOAPAction'  : 'http://www.webserviceX.NET/ConversionRate', //#|B\n  'Accept'      : 'application/soap+xml, text/*'               //#|B\n]\nreqProps.each { key,value -> conn.addRequestProperty(key,value) }\n\nconn.requestMethod = 'POST'\nconn.doOutput      = true\nconn.outputStream << new ByteArrayInputStream(request)          //#C\nif (conn.responseCode != conn.HTTP_OK) {\n   println \"Error - HTTP:${conn.responseCode}\"\n   return\n}\n\ndef resp   = new XmlParser().parse(conn.inputStream)            //#D\ndef serv   = new Namespace('http://www.webserviceX.NET/')\ndef result = serv.ConversionRateResult                          //#E\n\nprint   \"Current USD to EUR conversion rate: \"\nprintln resp.depthFirst().find{result == it.name()}.text()\n// Current USD to EUR conversion rate: 0.882\n//#A Templated envelope of SOAP request\n//#B Request headers to use every time\n//#C Send the request\n//#D Parse the response\n//#E Extract the result\n"
  },
  {
    "path": "listings/chap15/Listing_15_13_SOAP12_currency_httpb.groovy",
    "content": "@Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7.2')\nimport groovyx.net.http.RESTClient\nimport static groovyx.net.http.ContentType.XML\n\ndef base = 'http://www.webserviceX.NET/CurrencyConvertor.asmx'\ndef soapEnv = 'http://www.w3.org/2003/05/soap-envelope'\ndef contentType = 'application/soap+xml; charset=UTF-8'\nnew RESTClient(base).with {\n  parser.'application/soap+xml' = parser.'application/xml'          //#1\n  headers = ['Content-Type': contentType]                           //#2\n  post(requestContentType: XML, body: {\n    'soap:Envelope'('xmlns:soap': soapEnv) {\n      'soap:Body' {\n        ConversionRate(xmlns: 'http://www.webserviceX.NET/') {\n          FromCurrency('USD')\n          ToCurrency('EUR')\n        }\n      }\n    }\n  }) { resp, data ->\n    assert resp.status == 200\n    println data.text()\n  }\n}\n//#1 register a SOAP response parser\n//#2 Content-Type expected by SOAP server\n\n// xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\"\n// => http://www.webservicex.net/CurrencyConvertor.asmx/ConversionRate\n// => <double xmlns=\"http://www.webserviceX.NET/\">0.882</double>\n// => 0.882\n/*\n<soap:Envelope\n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n  xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n  <soap:Body>\n    <ConversionRate xmlns=\"http://www.webserviceX.NET/\">\n      <FromCurrency>${from}</FromCurrency>\n      <ToCurrency>${to}</ToCurrency>\n    </ConversionRate>\n  </soap:Body>\n</soap:Envelope>\n*/"
  },
  {
    "path": "listings/chap15/Listing_15_14_SOAP11_currency_wslite.groovy",
    "content": "@Grab('com.github.groovy-wslite:groovy-wslite:1.1.0')\nimport wslite.soap.SOAPClient\n\ndef url = 'http://www.webservicex.net/CurrencyConvertor.asmx?WSDL'\ndef client = new SOAPClient(url)\ndef action = \"http://www.webserviceX.NET/ConversionRate\"\ndef response = client.send(SOAPAction: action) {\n  body {\n    ConversionRate(xmlns: 'http://www.webserviceX.NET/') {\n      FromCurrency('USD')\n      ToCurrency('EUR')\n    }\n  }\n}\nassert response.httpResponse.statusCode == 200\nprintln response.ConversionRateResponse.ConversionRateResult\n// => 0.882\n"
  },
  {
    "path": "listings/chap15/Listing_15_15_SOAP12_currency_wslite.groovy",
    "content": "@Grab('com.github.groovy-wslite:groovy-wslite:1.1.0')\nimport wslite.soap.*\n\ndef url = 'http://www.webserviceX.NET/CurrencyConvertor.asmx?WSDL'\ndef client = new SOAPClient(url)\ndef response = client.send {\n  version SOAPVersion.V1_2\n  body {\n    ConversionRate(xmlns: 'http://www.webserviceX.NET/') {\n      FromCurrency('USD')\n      ToCurrency('EUR')\n    }\n  }\n}\nassert response.httpResponse.statusCode == 200\nprintln response.ConversionRateResponse.ConversionRateResult\n\n// => 0.882\n"
  },
  {
    "path": "listings/chap15/data/conv.templ.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<soap:Envelope\n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n  xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n  <soap:Body>\n    <ConversionRate xmlns=\"http://www.webserviceX.NET/\">\n      <FromCurrency>${from}</FromCurrency>\n      <ToCurrency>${to}</ToCurrency>\n    </ConversionRate>\n  </soap:Body>\n</soap:Envelope>\n"
  },
  {
    "path": "listings/chap16/HelloIntegrationWorld.java",
    "content": "// Java\nimport groovy.lang.GroovyShell;\n\npublic class HelloIntegrationWorld {\n    public static void main(String[] args) {\n        GroovyShell shell = new GroovyShell();\n        Object result = shell.evaluate(\"12+23\");\n        assert result.equals(35);\n    }\n}\n"
  },
  {
    "path": "listings/chap16/Listing_16_01_HelloIntegration.groovy",
    "content": "def shell = new GroovyShell()\ndef result = shell.evaluate(\"12 + 23\")\nassert result == 35\n"
  },
  {
    "path": "listings/chap16/Listing_16_02_HelloIntegrationJava.txt",
    "content": "see: HelloIntegrationWorld.java\n"
  },
  {
    "path": "listings/chap16/Listing_16_03_MultilineScript.groovy",
    "content": "def shell = new GroovyShell()\ndef kineticEnergy = shell.evaluate('''\n    def mass = 22.3\n    def velocity = 10.6\n    mass * velocity**2 / 2\n''')\nassert kineticEnergy == 1252.814\n"
  },
  {
    "path": "listings/chap16/Listing_16_04_UsingEval.groovy",
    "content": "assert \"Hello\" == Eval.me(\"'Hello'\")\nassert 1 == Eval.x  (1, \"x\")\nassert 3 == Eval.xy (1, 2, \"x+y\")\nassert 6 == Eval.xyz(1, 2, 3, \"x+y+z\")\n"
  },
  {
    "path": "listings/chap16/Listing_16_05_Binding.groovy",
    "content": "def binding = new Binding()                //#1\nbinding.mass = 22.3                        //#1\nbinding.velocity = 10.6                    //#1\n\ndef shell = new GroovyShell(binding)                       //#2\ndef expression = \"mass * velocity ** 2 / 2\"                //#2\nassert shell.evaluate(expression) == 1252.814              //#2\n\nbinding.setVariable(\"mass\", 25.4)                          //#3\nassert shell.evaluate(expression) == 1426.972              //#3\n//#1 Create and populate the binding\n//#2 Evaluate the expression using the binding\n//#3 Change the binding data and re-evaluate\n"
  },
  {
    "path": "listings/chap16/Listing_16_06_BindingTwoWay.groovy",
    "content": "def binding = new Binding(x: 6, y: 4)                       //#1\ndef shell = new GroovyShell(binding)\nshell.evaluate('''\n    xSquare = x * x                                         //#2\n    yCube   = y * y * y                                     //#2\n''')\nassert binding.getVariable(\"xSquare\") == 36                 //#3\nassert binding.yCube == 64                                  //#4\n//#1 Prepopulating the binding data\n//#2 Setting binding data within the evaluated script\n//#3 Method access to binding data\n//#4 Groovy property access to binding data\n"
  },
  {
    "path": "listings/chap16/Listing_16_07_ClassInScript.groovy",
    "content": "def shell = new GroovyShell()\ndef clazz = shell.evaluate('''\n    class MyClass {                //#A\n        def method() { \"value\" }   //#A\n    }                              //#A\n    return MyClass                 //#A\n''')\nassert clazz.name == \"MyClass\"\ndef instance = clazz.newInstance()       //#B\nassert instance.method() == \"value\"      //#C\n//#A Define a new class\n//#B Create an instance of the class\n//#C Use the object as normal\n"
  },
  {
    "path": "listings/chap16/Listing_16_08_Payment_calculator.groovy",
    "content": "def monthly = \"amount*(rate/12) / (1-(1+rate/12)**-numberOfMonths)\"\n\ndef shell = new GroovyShell()\ndef script = shell.parse(monthly)                         //#A\n\nscript.binding.amount = 154000                            //#B\nscript.rate = 3.75/100                                    //#C\nscript.numberOfMonths = 240\n\nassert script.run() == 913.0480050387338\n\nscript.binding = new Binding(amount: 185000,              //|#D\n                              rate: 3.50/100,             //|#D\n                              numberOfMonths: 300)        //|#D\n\nassert script.run() == 926.1536089487843\n//#A Parse formula into reusable script\n//#B Access binding variable\n//#C Access binding variable using shorthand\n//#D Create new binding\n"
  },
  {
    "path": "listings/chap16/Listing_16_09_MethodsInBinding.groovy",
    "content": "def binding = new Binding(multiply: { a, b -> a * b })       //#A\ndef shell = new GroovyShell(binding)\ndef value = shell.evaluate('''\n    multiply(5, 6)                                           //#B\n''')\nassert value == 30\n//#A Create closure within the binding\n//#B Call the closure like a normal method\n"
  },
  {
    "path": "listings/chap16/Listing_16_10_ShapeInfoMain.txt",
    "content": "see: shapes/ShapeInfoMain.java\n"
  },
  {
    "path": "listings/chap16/Listing_16_11_SpringConfig.txt",
    "content": "see: spring/beans.xml\n"
  },
  {
    "path": "listings/chap16/Listing_16_12_BeanToString.groovy",
    "content": "import groovy.transform.ToString\nimport org.codehaus.groovy.control.CompilerConfiguration\nimport org.codehaus.groovy.control.customizers.*\n\ndef conf = new CompilerConfiguration()\ndef astCustomizer = new ASTTransformationCustomizer(ToString)       //#1\ndef sourceAwareCustomizer =\n    new SourceAwareCustomizer(astCustomizer)                        //#2\nsourceAwareCustomizer.baseNameValidator = {                         //#3\n  name -> name.endsWith 'Bean'\n}\nconf.addCompilationCustomizers(sourceAwareCustomizer)\n\ndef gcl = new GroovyClassLoader(getClass().classLoader, conf)       //#4\ndef clazz = gcl.parseClass '''\nclass MrBean { String first, last }\n''', 'MrBean.groovy'\ndef result = clazz.newInstance()\nresult.first = 'Rowan'\nresult.last = 'Atkinson'\nassert result.toString() == 'MrBean(Rowan, Atkinson)'\n//#1 Create ToString AST customizer\n//#2 Wrap into a source aware customizer\n//#3 Create a basename filter\n//#4 Use conf with GroovyClassLoader\n"
  },
  {
    "path": "listings/chap16/shapes/Circle.groovy",
    "content": "package shapes\n\nclass Circle implements Shape {\n    double radius\n    Circle(double radius) { this.radius = radius }\n    double area() { return Math.PI * radius ** 2 }\n    double perimeter() { return 2 * Math.PI * radius }\n}\n"
  },
  {
    "path": "listings/chap16/shapes/MaxAreaInfo.groovy",
    "content": "package shapes\n\nclass MaxAreaInfo implements ShapeInfo {\n  void displayInfo(Shape s1, Shape s2) {\n    print \"The shape with the biggest area is: \"\n    println s1.area() > s2.area() ? s1.class.simpleName : s2.class.simpleName\n  }\n}\n"
  },
  {
    "path": "listings/chap16/shapes/MaxPerimeterInfo.java",
    "content": "package shapes;\n\npublic class MaxPerimeterInfo {\n    void displayInfo(Square s, Circle c) {\n        System.out.print(\"The shape with the biggest perimeter is: \");\n        System.out.println(s.perimeter() > c.perimeter() ? \"square\" : \"circle\");\n    }\n}\n"
  },
  {
    "path": "listings/chap16/shapes/Shape.java",
    "content": "package shapes;\n\npublic interface Shape {\n    double area();\n    double perimeter();\n}\n"
  },
  {
    "path": "listings/chap16/shapes/ShapeInfo.java",
    "content": "package shapes;\n\npublic interface ShapeInfo {\n    void displayInfo(Shape s1, Shape s2);\n}\n"
  },
  {
    "path": "listings/chap16/shapes/ShapeInfoMain.java",
    "content": "package shapes;\n\n// Java\npublic class ShapeInfoMain {\n    public static void main(String[] args) {\n        Square s = new Square(7);\n        Circle c = new Circle(4);\n        new MaxAreaInfo().displayInfo(s, c);\n        new MaxPerimeterInfo().displayInfo(s, c);\n    }\n}\n"
  },
  {
    "path": "listings/chap16/shapes/Square.java",
    "content": "package shapes;\n\npublic class Square implements Shape {\n    private double side;\n    Square(double side) { this.side = side; }\n    public double area() { return side * side; }\n    public double perimeter() { return 4 * side; }\n}\n"
  },
  {
    "path": "listings/chap16/spring/common/Shape.java",
    "content": "package spring.common;\n\npublic interface Shape {\n    double area();\n    double perimeter();\n}\n"
  },
  {
    "path": "listings/chap16/spring/common/ShapeInfo.java",
    "content": "package spring.common;\n\npublic interface ShapeInfo {\n    void displayInfo(Shape s1, Shape s2);\n}\n"
  },
  {
    "path": "listings/chap16/spring/groovy/Circle.groovy",
    "content": "package spring.groovy\n\nimport spring.common.Shape\n\nclass Circle implements Shape {\n    double radius\n    String color = \"Blue\"\n    Circle(double radius) { this.radius = radius }\n    double area() { return Math.PI * radius ** 2 }\n    double perimeter() { return 2 * Math.PI * radius }\n    String toString() { return color + \" Groovy Circle\" }\n}\n"
  },
  {
    "path": "listings/chap16/spring/groovy/MaxAreaInfo.groovy",
    "content": "package spring.groovy\n\nimport spring.common.Shape\nimport spring.common.ShapeInfo\n\nclass MaxAreaInfo implements ShapeInfo {\n    void displayInfo(Shape s1, Shape s2) {\n        print \"The shape with the biggest area is: \"\n        if (s1.area() > s2.area()) println s1 else println s2\n    }\n}\n"
  },
  {
    "path": "listings/chap16/spring/java/MaxPerimeterInfo.java",
    "content": "package spring.java;\n\nimport spring.common.Shape;\nimport spring.common.ShapeInfo;\n\npublic class MaxPerimeterInfo implements ShapeInfo {\n    public String getPrefix() {\n        return null;\n    }\n\n    public void setPrefix(String value) {\n    }\n\n    public void displayInfo(Shape s1, Shape s2) {\n        System.out.print(\"The shape with the biggest perimeter is: \");\n        System.out.println(s1.perimeter() > s2.perimeter() ? s1.getClass().getName()\n                                                           : s2.getClass().getName());\n    }\n}\n"
  },
  {
    "path": "listings/chap16/spring/java/ShapeInfoFactoryMain.java",
    "content": "package spring.java;\n\nimport spring.common.Shape;\nimport spring.common.ShapeInfo;\n\nimport java.lang.reflect.Constructor;\n\npublic class ShapeInfoFactoryMain\n{\n    public static void main(String[] args) {\n        try {\n            Shape s = new Square(7);\n            Class groovyCircle = Class.forName(\"spring.groovy.Circle\");\n            Class groovyMaxAreaInfo = Class.forName(\"spring.groovy.MaxAreaInfo\");\n            Constructor cons = groovyCircle.getConstructors()[0];\n            Shape c = (Shape) cons.newInstance(4);\n            ShapeInfo info = (ShapeInfo) groovyMaxAreaInfo.newInstance();\n            info.displayInfo(s, c);\n            new MaxPerimeterInfo().displayInfo(s, c);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n}\n"
  },
  {
    "path": "listings/chap16/spring/java/ShapeInfoMain.java",
    "content": "package spring.java;\n\nimport spring.groovy.Circle;\nimport spring.groovy.MaxAreaInfo;\nimport spring.common.Shape;\n\npublic class ShapeInfoMain\n{\n    public static void main(String[] args) {\n        Shape s = new Square(7);\n        Shape c = new Circle(4);\n        new MaxAreaInfo().displayInfo(s, c);\n        new MaxPerimeterInfo().displayInfo(s, c);\n    }\n}\n"
  },
  {
    "path": "listings/chap16/spring/java/ShapeInfoSpringMain.java",
    "content": "package spring.java;\n\nimport spring.common.Shape;\nimport spring.common.ShapeInfo;\n\n//import org.springframework.core.io.Resource;\n//import org.springframework.core.io.FileSystemResource;\n//import org.springframework.beans.factory.xml.XmlBeanFactory;\n//import org.springframework.beans.factory.BeanFactory;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.support.ClassPathXmlApplicationContext;\n\npublic class ShapeInfoSpringMain\n{\n    public static void main(String[] args) {\n        try {\n            ApplicationContext ctx = new ClassPathXmlApplicationContext(\"beans.xml\");\n//            Resource resource = new FileSystemResource(\"spring/beans.xml\");\n//            BeanFactory factory = new XmlBeanFactory(resource);\n            Shape s = new Square(7);\n            Shape c = (Shape) ctx.getBean(\"circle\");\n            ShapeInfo info = (ShapeInfo) ctx.getBean(\"maxareainfo3\");\n            info.displayInfo(s, c);\n            new MaxPerimeterInfo().displayInfo(s, c);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n    }\n}\n"
  },
  {
    "path": "listings/chap16/spring/java/Square.java",
    "content": "package spring.java;\n\nimport spring.common.Shape;\n\npublic class Square implements Shape {\n    private double side;\n    private String color = \"White\";\n    public Square(double side) { this.side = side; }\n    public double area() { return side * side; }\n    public double perimeter() { return 4 * side; }\n    public String toString(){ return color + \" Java Square\"; }\n}\n"
  },
  {
    "path": "listings/chap16/spring/resources/beans.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\nxmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\nxmlns:lang=\"http://www.springframework.org/schema/lang\"\nxsi:schemaLocation=\"\nhttp://www.springframework.org/schema/beans\n  http://www.springframework.org/schema/beans/spring-beans.xsd\nhttp://www.springframework.org/schema/lang\n  http://www.springframework.org/schema/lang/spring-lang.xsd\">\n<bean id=\"circle\" class=\"spring.groovy.Circle\">\n    <constructor-arg value=\"4\"/>\n    <property name=\"color\" value=\"Black\"/>\n</bean>\n<!-- same beans.xml file used for three different scenarios -->\n<!-- uncomment the relevant section when working through snippets -->\n<!--\n<bean id=\"maxareainfo\" class=\"spring.groovy.MaxAreaInfo\"/>\n-->\n<lang:groovy id=\"maxareainfo2\" script-source=\"classpath:MaxAreaInfo.groovy\">\n    <lang:property name=\"prefix\" value=\"Live Groovy says\" />\n</lang:groovy>\n<!--\n<lang:groovy id=\"maxareainfo3\" script-interfaces=\"spring.common.ShapeInfo\" >\n    <lang:inline-script>\n    import spring.common.Shape\n    import spring.common.ShapeInfo\n\n    class SuffixMaxAreaInfo implements ShapeInfo {\n        String suffix\n        void displayInfo(Shape s1, Shape s2) {\n            print \"The shape with the biggest area is: \"\n            if (s1.area() > s2.area()) println s1 + \":\" + suffix else println s2 + \":\" + suffix\n        }\n    }\n    </lang:inline-script>\n    <lang:property name=\"suffix\" value=\"Did you guess correctly?\" />\n</lang:groovy>\n-->\n</beans>"
  },
  {
    "path": "listings/chap17/.classpath",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<classpath>\n\t<classpathentry kind=\"con\" path=\"org.eclipse.jdt.launching.JRE_CONTAINER\"/>\n\t<classpathentry kind=\"src\" path=\"\"/>\n\t<classpathentry kind=\"con\" path=\"org.eclipse.jdt.USER_LIBRARY/groovy-2.4.0.rc-1\"/>\n\t<classpathentry kind=\"var\" path=\"USER_HOME/.groovy/grapes/net.java.quickcheck/quickcheck/jars/quickcheck-0.6.jar\"/>\n\t<classpathentry kind=\"var\" path=\"USER_HOME/.groovy/grapes/net.java.quickcheck/quickcheck-src-generator/jars/quickcheck-src-generator-0.6.jar\"/>\n\t<classpathentry kind=\"var\" path=\"USER_HOME/.groovy/grapes/org.spockframework/spock-core/jars/spock-core-0.7-groovy-2.0.jar\"/>\n\t<classpathentry kind=\"var\" path=\"USER_HOME/.groovy/grapes/junit/junit-dep/jars/junit-dep-4.10.jar\"/>\n\t<classpathentry kind=\"var\" path=\"USER_HOME/.groovy/grapes/org.hamcrest/hamcrest-core/jars/hamcrest-core-1.3.jar\"/>\n\t<classpathentry kind=\"var\" path=\"USER_HOME/.groovy/grapes/junitperf/junitperf/jars/junitperf-1.9.1.jar\"/>\n\t<classpathentry kind=\"lib\" path=\"C:/devtools/groovy-2.4.0/embeddable/groovy-all-2.4.0.jar\"/>\n\t<classpathentry kind=\"lib\" path=\"C:/devtools/groovy-2.4.0/lib/junit-4.12.jar\"/>\n\t<classpathentry kind=\"lib\" path=\"C:/devtools/groovy-2.4.0/lib/ant-1.9.4.jar\"/>\n\t<classpathentry exported=\"true\" kind=\"con\" path=\"GROOVY_DSL_SUPPORT\"/>\n\t<classpathentry kind=\"lib\" path=\"C:/devtools/groovy-2.4.0/lib/ant-launcher-1.9.4.jar\"/>\n\t<classpathentry kind=\"output\" path=\"bin\"/>\n</classpath>\n"
  },
  {
    "path": "listings/chap17/.project",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<projectDescription>\n\t<name>chap17</name>\n\t<comment></comment>\n\t<projects>\n\t</projects>\n\t<buildSpec>\n\t\t<buildCommand>\n\t\t\t<name>org.eclipse.jdt.core.javabuilder</name>\n\t\t\t<arguments>\n\t\t\t</arguments>\n\t\t</buildCommand>\n\t</buildSpec>\n\t<natures>\n\t\t<nature>org.eclipse.jdt.groovy.core.groovyNature</nature>\n\t\t<nature>org.eclipse.jdt.core.javanature</nature>\n\t</natures>\n</projectDescription>\n"
  },
  {
    "path": "listings/chap17/Converter.groovy",
    "content": "class Converter {\n    static celsius (fahrenheit) { (fahrenheit - 32) * 5 / 9 }\n}\n"
  },
  {
    "path": "listings/chap17/Counter.groovy",
    "content": "class Counter {\n    int biggerThan(items, threshold) {\n        items.grep{ it > threshold }.size()\n    }\n}\n"
  },
  {
    "path": "listings/chap17/Farm.groovy",
    "content": "class Farm {\n    def getMachines() {\n        /* some expensive code here */\n        throw new RuntimeException('should not reach here')\n    }\n}"
  },
  {
    "path": "listings/chap17/Listing_17_01_Celsius.groovy",
    "content": "import static Converter.celsius\n\nassert  20 == celsius(68)\nassert  35 == celsius(95)\nassert -17 == celsius(0).toInteger()                //#A\nassert   0 == celsius(32)\n//#A Round down to whole number\n"
  },
  {
    "path": "listings/chap17/Listing_17_02_CounterTest.groovy",
    "content": "class Listing_17_02_CounterTest extends GroovyTestCase {\n  static final Integer[] NEG_NUMBERS   = [-2, -3, -4]             //#A\n  static final Integer[] POS_NUMBERS   = [4,   5,  6]             //#A\n  static final Integer[] MIXED_NUMBERS = [4,  -6,  0]             //#A\n  private Counter counter\n\n  void setUp() {\n    counter = new Counter()\n  }\n\n  void testCounterWorks() {\n    assertEquals(2, counter.biggerThan([5, 10, 15], 7))\n  }\n\n  void testCountHowManyFromSampleNumbers() {\n    check(0, NEG_NUMBERS, -1)                         //#B\n    check(0, NEG_NUMBERS, -2)                         //#B\n    check(2, NEG_NUMBERS, -4)                         //#B\n    check(3, NEG_NUMBERS, -5)                         //#B\n    check(0, POS_NUMBERS,  7)                         //#B\n    check(0, POS_NUMBERS,  6)                         //#B\n    check(2, POS_NUMBERS,  4)                         //#B\n    check(3, POS_NUMBERS,  3)                         //#B\n    check(0, MIXED_NUMBERS,  5)                       //#B\n    check(1, MIXED_NUMBERS,  2)                       //#B\n    check(1, MIXED_NUMBERS,  1)                       //#B\n    check(1, MIXED_NUMBERS,  0)                       //#B\n    check(2, MIXED_NUMBERS, -1)                       //#B\n    check(3, MIXED_NUMBERS, -7)                       //#B\n  }\n\n  void testInputDataUnchanged() {                       //#C\n    def numbers = NEG_NUMBERS.clone()\n    def origLength = numbers.size()\n    counter.biggerThan(numbers, 0 /* don't care */)\n    assertLength origLength, numbers\n    assertArrayEquals NEG_NUMBERS, numbers\n  }\n\n  void testCountHowManyFromSampleStrings() {            //#D\n    check(2, ['Dog', 'Cat', 'Antelope'], 'Bird')\n  }\n\n  void testInputDataAssumptions() {                    //#E\n    assertTrue NEG_NUMBERS.every { it < 0 }\n    assertTrue POS_NUMBERS.every { it > 0 }\n    assertContains 0, MIXED_NUMBERS\n    int negCount = 0\n    int posCount = 0\n    MIXED_NUMBERS.each {\n      if (it < 0) negCount++ else if (it > 0) posCount++\n    }\n    assert negCount && posCount\n  }\n\n  private check(expectedCount, items, threshold) {\n    assertEquals(expectedCount,\n        counter.biggerThan(items, threshold)\n    )\n  }\n}\n//#A Constants repeated in the test\n//#B Use a helper method to make code simpler\n//#C Tests proving we don’t change the array\n//#D Calculator doesn’t only work with numbers\n//#E Test constants sanity check\n\n"
  },
  {
    "path": "listings/chap17/Listing_17_03_HashMapTest.groovy",
    "content": "class Listing_17_03_HashMapTest extends GroovyTestCase {\n  static final KEY = new Object()\n  static final MAP = [key1: new Object(), key2: new Object()]\n\n  void testHashtableRejectsNull() {\n    shouldFail(NullPointerException) {\n      new Hashtable()[KEY] = null\n    }\n  }\n\n  void testBadInitialSize() {\n    def msg = shouldFail(IllegalArgumentException) {     //#A\n      new HashMap(-1)\n    }\n    assertEquals \"Illegal initial capacity: -1\", msg             //#B\n  }\n\n  void testHashMapAcceptsNull() {\n    def myMap = new HashMap()\n    myMap[KEY] = null\n    assert myMap.keySet().contains(KEY)\n  }\n\n  void testHashMapReturnsOriginalObjects() {\n    def myMap = new HashMap()\n    MAP.entrySet().each {\n      myMap[it] = MAP[it]\n      assertSame MAP[it], myMap[it]\n    }\n    assert MAP.dump().contains('java.lang.Object')       //#C\n    assert myMap.size() == MAP.size()\n  }\n}\n//#A Check that the right kind of exception is thrown\n//#B Check the message\n//#C Use Groovy inspection to examine the map\n"
  },
  {
    "path": "listings/chap17/Listing_17_04_GroovyTestSuite.groovy",
    "content": "import junit.framework.*\nimport junit.textui.TestRunner\n\nstatic Test suite() {\n  def suite = new TestSuite()\n  def gts = new GroovyTestSuite()\n  suite.addTestSuite(gts.compile(\"Listing_17_02_CounterTest.groovy\"))\n  suite.addTestSuite(gts.compile(\"Listing_17_03_HashMapTest.groovy\"))\n  return suite\n}\n\nTestRunner.run(suite())\n"
  },
  {
    "path": "listings/chap17/Listing_17_05_AllTestSuite.groovy",
    "content": "def suite = AllTestSuite.suite(\".\", \"Listing_17_*Counter*Test.groovy\")\njunit.textui.TestRunner.run(suite)\n"
  },
  {
    "path": "listings/chap17/Listing_17_06_DataDrivenJUnitTest.groovy",
    "content": "import org.junit.Test\nimport org.junit.runner.RunWith\nimport org.junit.runners.Parameterized\nimport org.junit.runners.Parameterized.Parameters\nimport static Converter.celsius\n\n@RunWith(Parameterized)                                    //#1\nclass Listing_17_06_DataDrivenJUnitTest {\n  private c, f, scenario\n\n  @Parameters static scenarios() {[                        //#2\n      [0,   32,  'Freezing'],\n      [20,  68,  'Garden party conditions'],\n      [35,  95,  'Beach conditions'],\n      [100, 212, 'Boiling']\n  ]*.toArray()}\n\n  Listing_17_06_DataDrivenJUnitTest(c, f, scenario) {      //#3\n    this.c = c\n    this.f = f\n    this.scenario = scenario\n  }\n\n  @Test void convert() {\n    def actual = celsius(f)\n    def msg = \"$scenario: ${f}°F should convert into ${c}°C\"\n    assert c == actual, msg\n  }\n}\n//#1 Special test runner\n//#2 Array of test data\n//#3 Constructor parameters consume a row of test data\n"
  },
  {
    "path": "listings/chap17/Listing_17_07_PropertyBased.groovy",
    "content": "@Grab('net.java.quickcheck:quickcheck:0.6')\nimport static net.java.quickcheck.generator.PrimitiveGenerators.*\nimport static java.lang.Math.round\nimport static Converter.celsius\n\ndef gen = integers(-40, 240)                         //#1\ndef liquidC =  0..100\ndef liquidF = 32..212\n100.times {\n  int f = gen.next()                                 //#2\n  int c = round(celsius(f))\n  assert c <= f                                      //#3\n  assert c in liquidC == f in liquidF                //#4\n}\n//#1 Select integers from this range\n//#2 Get the next integer\n//#3 Celsius less than Fahrenheit (above -40 degrees)\n//#4 Water should be liquid in this range\n"
  },
  {
    "path": "listings/chap17/Listing_17_08_Balancer.groovy",
    "content": "import static org.junit.Assert.assertSame\n\ndef relay(request, farm) {                             //#|A\n    farm.machines.sort { it.load }[0].send(request)    //#|A\n}                                                      //#|A\n\nclass FakeMachine {                                    //#B\n    def load\n    def send(request) { return this }\n}\n\nfinal LOW_LOAD = 5, HIGH_LOAD = 10\ndef farm = [machines: [                                //#|C\n    new FakeMachine(load:HIGH_LOAD),                   //#|C\n    new FakeMachine(load:LOW_LOAD)]]                   //#|C\n\nassertSame(LOW_LOAD, relay(null, farm).load)\n//#A Subject under test\n//#B Replacement class\n//#C Map replaces farm\n"
  },
  {
    "path": "listings/chap17/Listing_17_09_BalancerStub.groovy",
    "content": "import groovy.mock.interceptor.StubFor\n\ndef relay(request) {\n    new Farm().getMachines().sort { it.load }[0].send(request)\n}\n\ndef fakeOne = new Expando(load:10, send: { false } )\ndef fakeTwo = new Expando(load:5,  send: { true }  )\n\ndef farmStub = new StubFor(Farm)                        //#A\nfarmStub.demand.getMachines { [fakeOne, fakeTwo ] }     //#B\n\nfarmStub.use {                                          //#|C\n    assert relay(null)                                  //#|C\n}                                                       //#|C\n//#A Create stub\n//#B Specify demanded behavior\n//#C Call the class under test using stub\n"
  },
  {
    "path": "listings/chap17/Listing_17_10_BalancerMock.groovy",
    "content": "import groovy.mock.interceptor.MockFor\n\nclass SortableFarm extends Farm {\n    void sort() {\n        /* here the Farm would sort its machines by load */\n    }\n}\n\ndef relay(request) {\n    def farm = new SortableFarm()\n    farm.sort()\n    farm.getMachines()[0].send(request)\n}\n\ndef farmMock = new MockFor(SortableFarm)                    //#A\n\nfarmMock.demand.sort(){}                                    //#|B\nfarmMock.demand.getMachines { [new Expando(send: {} )] }    //#|B\n\nfarmMock.use {\n    relay(null)\n}\n//#A Create mock\n//#B Specify demanded behavior\n"
  },
  {
    "path": "listings/chap17/Listing_17_11_LoggingCounterTest.groovy",
    "content": "import java.util.logging.Level\n\nclass Listing_17_11_LoggingCounterTest extends GroovyLogTestCase {\n  static final MIXED_NUMBERS = [99, 2, 1, 0, -1, -2, -99]        //#A\n  private count\n\n  void setUp() {\n    count = new LoggingCounter()\n  }\n\n  void testCounterAndLog() {\n    def log = stringLog(Level.FINER, 'LoggingCounter') {         //#B\n      def bigger = count.biggerThan(MIXED_NUMBERS, -1)           //#C\n      assertEquals(4, bigger)                                    //#D\n    }\n    checkLogCount(1, \"was equal\", log)\n    checkLogCount(4, \"was bigger\", log)\n    checkLogCount(2, \"was smaller\", log)\n    checkLogCount(4, /[^d][^o][^n][^'][^t] count this one/, log)\n    checkLogCount(3, \"don't count this one\", log)\n  }\n\n  private checkLogCount(expectedCount, regex, log) {             //#E\n    def matcher = (log =~ regex)\n    assertTrue log, expectedCount == matcher.count\n  }\n}\n//#A Test data\n//#B Set up stringLog\n//#C Invoke SUT\n//#D Traditional JUnit style assert\n//#E Helper method asserting patterns within the log\n\n"
  },
  {
    "path": "listings/chap17/Listing_17_12_JUnitPerf.groovy",
    "content": "@Grab('junitperf:junitperf:1.9.1')\n@GrabResolver('https://repository.jboss.org/')\nimport com.clarkware.junitperf.*\nimport junit.framework.*\nimport junit.textui.TestRunner\nimport static Converter.celsius\n\nclass Listing_17_12_JUnitPerf extends TestCase {\n  Listing_17_12_JUnitPerf(String testName) {\n    super(testName)                                                 //#A\n  }\n\n  void testConverter() {                                            //#B\n    assert 0 == celsius(32)                                         //#C\n    assert 100 == celsius(212)                                      //#C\n  }\n\n  static main(args) {\n    TestRunner.run(suite())\n  }\n\n  static Test suite() {\n    def testCase = new Listing_17_12_JUnitPerf(\"testConverter\")     //#D\n\n    def numUsers = 20                                               //#E\n    def stagger = new ConstantTimer(100)                            //#E\n    def loadTest = new LoadTest(testCase, numUsers, stagger)        //#F\n\n    def timeLimit = 2100                                            //#G\n    return new TimedTest(loadTest, timeLimit)                       //#H\n  }\n}\n//#A Call super\n//#B Traditional nontimed JUnit test\n//#C Class under test\n//#D Define test case\n//#E 20 users for load staggered at 100 ms\n//#F Decorate testcase to simulate load\n//#G Must return within 2100 ms\n//#H Return decorated time-constrained test\n"
  },
  {
    "path": "listings/chap17/Listing_17_13_SpockSimple.groovy",
    "content": "@Grab('org.spockframework:spock-core:1.0-groovy-2.4')\nimport spock.lang.Specification\n\nclass GivenWhenThenSpec extends Specification {\n\n  def \"test adding a new item to a set\"() {\n    given:\n    def items = [4, 6, 3, 2] as Set\n\n    when:\n    items << 1\n\n    then:\n    items.size() == 5\n  }\n}\n"
  },
  {
    "path": "listings/chap17/Listing_17_14_SpockMock.groovy",
    "content": "@Grab('org.spockframework:spock-core:1.0-groovy-2.4')\nimport spock.lang.Specification\n\nclass Listing_17_14_SpockMock extends Specification {\n  def \"buy ticket for a movie theater\"() {\n    given:\n    def purchase = new Purchase(\"Lord of the Rings\", 2)\n    MovieTheater theater = Mock()                                 //#A\n    theater.hasSeatsAvailable(\"Lord of the Rings\", 2) >> true     //#B\n\n    when:\n    purchase.fill(theater)\n\n    then:\n    purchase.completed\n    1 * theater.purchaseTicket(\"Lord of the Rings\", 2)            //#C\n  }\n}\n//#A Creation of mock theater\n//#B Mock hasSeatsAvailable call returning true\n//#C Assert purchaseTicket has been called 1 time\n"
  },
  {
    "path": "listings/chap17/Listing_17_15_SpockMockWildcards.groovy",
    "content": "@Grab('org.spockframework:spock-core:1.0-groovy-2.4')\nimport spock.lang.Specification\n\nclass Listing_17_15_SpockMockWildcards extends Specification {\n  def \"cannot buy a ticket when the movie is sold out\"() {\n    given:\n    def purchase = new Purchase(\"Lord of the rings\", 2)\n    MovieTheater theater = Mock()\n\n    when:\n    theater.hasSeatsAvailable(_, _) >> false               //#A\n    purchase.fill(theater)\n\n    then:\n    !purchase.completed\n    0 * theater.purchaseTicket(_, _)                       //#B\n  }\n}\n//#A Mock hasSeatsAvailable call, any args, return false\n//#B The purchaseTicket method has not been called\n\n\n"
  },
  {
    "path": "listings/chap17/Listing_17_16_SpockMockClosureChecks.groovy",
    "content": "@Grab('org.spockframework:spock-core:1.0-groovy-2.4')\nimport spock.lang.Specification\n\nclass Listing_17_16_SpockMockClosureChecks extends Specification {\n  def \"on couples night tickets are sold in pairs\"() {\n    given:\n    def purchase = new Purchase(\"Lord of the Rings\", 2)\n    MovieTheater theater = Mock()\n    theater.hasSeatsAvailable(\"Lord of the Rings\", 2) >> true\n\n    when:\n    purchase.fill(theater)\n\n    then:\n    1 * theater.purchaseTicket(_, { it % 2 == 0 })            //#1\n  }\n}\n//#1 Closure argument checking\n\n"
  },
  {
    "path": "listings/chap17/Listing_17_17_SpockDataDriven.groovy",
    "content": "@Grab('org.spockframework:spock-core:1.0-groovy-2.4')\nimport spock.lang.*\n\nimport static Converter.celsius\n\nclass Listing_17_17_SpockDataDriven extends Specification {\n  @Unroll\n//  def \"test temperature scenarios\"() {\n    def \"Scenario #scenario: #tempFºF should convert to #tempCºC\"() {\n    expect:\n    celsius(tempF) == tempC\n\n    where:\n    scenario                  | tempF || tempC\n    'Freezing'                |    32 ||     0\n    'Garden party conditions' |    68 ||    20\n    'Beach conditions'        |    95 ||    35\n    'Boiling'                 |   212 ||   100\n  }\n}\n"
  },
  {
    "path": "listings/chap17/LoggingCounter.groovy",
    "content": "import java.util.logging.*\n\nclass LoggingCounter {\n    static final LOG = Logger.getLogger('LoggingCounter')\n\n    def biggerThan(items, target) {\n        int count = 0\n        items.each {\n            if (it > target) {\n                count++\n                LOG.finer \"item was bigger - count this one\"\n            } else if (it == target) {\n                LOG.finer \"item was equal - don't count this one\"\n            } else {\n                LOG.finer \"item was smaller - don't count this one\"\n            }\n        }\n        return count\n    }\n}\n"
  },
  {
    "path": "listings/chap17/MovieTheater.groovy",
    "content": "interface MovieTheater {\n  void purchaseTicket(name, number)\n  boolean hasSeatsAvailable(name, number)\n}\n"
  },
  {
    "path": "listings/chap17/Purchase.groovy",
    "content": "import groovy.transform.TupleConstructor\n\n@TupleConstructor\nclass Purchase {\n  def name, number, completed = false\n\n  def fill(theater) {\n    if (theater.hasSeatsAvailable(name, number)) {\n      theater.purchaseTicket(name, number)\n      completed = true\n    }\n  }\n}\n"
  },
  {
    "path": "listings/chap17/automation/build.gradle",
    "content": "apply plugin: 'groovy'\n\nversion = '1.0'\n\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    compile \"org.codehaus.groovy:groovy-all:2.4.0\"\n    testCompile \"junit:junit:4.12\"\n}\n\ntask initProject () << {\n  if (hasProperty(initPlugins)) {\n    initPlugins.split(',').each { plug ->\n      project.apply {\n        plugin(plug.trim())\n      }\n    }\n  }\n\n  project.sourceSets*.allSource.srcDirTrees.flatten().dir.each { dir ->\n    dir.mkdirs()\n  }\n}\n"
  },
  {
    "path": "listings/chap17/automation/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Thu Apr 10 09:16:15 EST 2014\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=http\\://services.gradle.org/distributions/gradle-2.2.1-bin.zip\n"
  },
  {
    "path": "listings/chap17/automation/gradlew",
    "content": "#!/bin/bash\n\n##############################################################################\n##                                                                          ##\n##  Gradle wrapper script for UN*X                                         ##\n##                                                                          ##\n##############################################################################\n\n# Uncomment those lines to set JVM options. GRADLE_OPTS and JAVA_OPTS can be used together.\nGRADLE_OPTS=\"$GRADLE_OPTS -Xmx640m\"\n# JAVA_OPTS=\"$JAVA_OPTS -Xmx512m\"\n\nGRADLE_APP_NAME=Gradle\n\nwarn ( ) {\n    echo \"${PROGNAME}: $*\"\n}\n\ndie ( ) {\n    warn \"$*\"\n    exit 1\n}\n\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set JAVA_HOME if it's not already set.\nif [ -z \"$JAVA_HOME\" ] ; then\n    if $darwin ; then\n        [ -z \"$JAVA_HOME\" -a -d \"/Library/Java/Home\" ] && export JAVA_HOME=\"/Library/Java/Home\"\n        [ -z \"$JAVA_HOME\" -a -d \"/System/Library/Frameworks/JavaVM.framework/Home\" ] && export JAVA_HOME=\"/System/Library/Frameworks/JavaVM.framework/Home\"\n    else\n        javaExecutable=\"`which javac`\"\n        [ -z \"$javaExecutable\" -o \"`expr \\\"$javaExecutable\\\" : '\\([^ ]*\\)'`\" = \"no\" ] && die \"JAVA_HOME not set and cannot find javac to deduce location, please set JAVA_HOME.\"\n        # readlink(1) is not available as standard on Solaris 10.\n        readLink=`which readlink`\n        [ `expr \"$readLink\" : '\\([^ ]*\\)'` = \"no\" ] && die \"JAVA_HOME not set and readlink not available, please set JAVA_HOME.\"\n        javaExecutable=\"`readlink -f \\\"$javaExecutable\\\"`\"\n        javaHome=\"`dirname \\\"$javaExecutable\\\"`\"\n        javaHome=`expr \"$javaHome\" : '\\(.*\\)/bin'`\n        export JAVA_HOME=\"$javaHome\"\n    fi\nfi\n\n# For Cygwin, ensure paths are in UNIX format before anything is touched.\nif $cygwin ; then\n    [ -n \"$JAVACMD\" ] && JAVACMD=`cygpath --unix \"$JAVACMD\"`\n    [ -n \"$JAVA_HOME\" ] && JAVA_HOME=`cygpath --unix \"$JAVA_HOME\"`\nfi\n\nSTARTER_MAIN_CLASS=org.gradle.wrapper.GradleWrapperMain\nCLASSPATH=`dirname \"$0\"`/gradle/wrapper/gradle-wrapper.jar\nWRAPPER_PROPERTIES=`dirname \"$0\"`/gradle/wrapper/gradle-wrapper.properties\n# Determine the Java command to use to start the JVM.\nif [ -z \"$JAVACMD\" ] ; then\n    if [ -n \"$JAVA_HOME\" ] ; then\n        if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n            # IBM's JDK on AIX uses strange locations for the executables\n            JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n        else\n            JAVACMD=\"$JAVA_HOME/bin/java\"\n        fi\n    else\n        JAVACMD=\"java\"\n    fi\nfi\nif [ ! -x \"$JAVACMD\" ] ; then\n    die \"JAVA_HOME is not defined correctly, can not execute: $JAVACMD\"\nfi\nif [ -z \"$JAVA_HOME\" ] ; then\n    warn \"JAVA_HOME environment variable is not set\"\nfi\n\n# For Darwin, add GRADLE_APP_NAME to the JAVA_OPTS as -Xdock:name\nif $darwin; then\n    JAVA_OPTS=\"$JAVA_OPTS -Xdock:name=$GRADLE_APP_NAME\"\n# we may also want to set -Xdock:image\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    JAVA_HOME=`cygpath --path --mixed \"$JAVA_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done \n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\nGRADLE_APP_BASE_NAME=`basename \"$0\"`\n\n\"$JAVACMD\" $JAVA_OPTS $GRADLE_OPTS \\\n        -classpath \"$CLASSPATH\" \\\n        -Dorg.gradle.appname=\"$GRADLE_APP_BASE_NAME\" \\\n        -Dorg.gradle.wrapper.properties=\"$WRAPPER_PROPERTIES\" \\\n        $STARTER_MAIN_CLASS \\\n        \"$@\"\n"
  },
  {
    "path": "listings/chap17/automation/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem                                                                         ##\n@rem  Gradle startup script for Windows                                      ##\n@rem                                                                         ##\n@rem ##########################################################################\n\n@rem\n@rem $Revision: 10602 $ $Date: 2008-01-25 02:49:54 +0100 (ven., 25 janv. 2008) $\n@rem\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Uncomment those lines to set JVM options. GRADLE_OPTS and JAVA_OPTS can be used together.\n@rem set GRADLE_OPTS=%GRADLE_OPTS% -Xmx512m\n@rem set JAVA_OPTS=%JAVA_OPTS% -Xmx512m\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\\\n\n@rem Determine the command interpreter to execute the \"CD\" later\nset COMMAND_COM=\"cmd.exe\"\nif exist \"%SystemRoot%\\system32\\cmd.exe\" set COMMAND_COM=\"%SystemRoot%\\system32\\cmd.exe\"\nif exist \"%SystemRoot%\\command.com\" set COMMAND_COM=\"%SystemRoot%\\command.com\"\n\n@rem Use explicit find.exe to prevent cygwin and others find.exe from being used\nset FIND_EXE=\"find.exe\"\nif exist \"%SystemRoot%\\system32\\find.exe\" set FIND_EXE=\"%SystemRoot%\\system32\\find.exe\"\nif exist \"%SystemRoot%\\command\\find.exe\" set FIND_EXE=\"%SystemRoot%\\command\\find.exe\"\n\n:check_JAVA_HOME\n@rem Make sure we have a valid JAVA_HOME\nif not \"%JAVA_HOME%\" == \"\" goto have_JAVA_HOME\n\necho.\necho ERROR: Environment variable JAVA_HOME has not been set.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\necho.\ngoto end\n\n:have_JAVA_HOME\n@rem Validate JAVA_HOME\n%COMMAND_COM% /C DIR \"%JAVA_HOME%\" 2>&1 | %FIND_EXE% /I /C \"%JAVA_HOME%\" >nul\nif not errorlevel 1 goto init\n\necho.\necho ERROR: JAVA_HOME might be set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation if there are problems.\necho.\n\n:init\n@rem get name of script to launch with full path\n@rem Get command-line arguments, handling Windowz variants\nSET _marker=%JAVA_HOME: =%\n@rem IF NOT \"%_marker%\" == \"%JAVA_HOME%\" ECHO JAVA_HOME \"%JAVA_HOME%\" contains spaces. Please change to a location without spaces if this causes problems.\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%eval[2+2]\" == \"4\" goto 4NT_args\n\nIF \"%_marker%\" == \"%JAVA_HOME%\" goto :win9xME_args\n\nset _FIXPATH=\ncall :fixpath \"%JAVA_HOME%\"\nset JAVA_HOME=%_FIXPATH:~1%\n\ngoto win9xME_args\n\n:fixpath\nif not %1.==. (\nfor /f \"tokens=1* delims=;\" %%a in (%1) do (\ncall :shortfilename \"%%a\" & call :fixpath \"%%b\"\n)\n)\ngoto :EOF\n:shortfilename\nfor %%i in (%1) do set _FIXPATH=%_FIXPATH%;%%~fsi\ngoto :EOF\n\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset STARTER_MAIN_CLASS=org.gradle.wrapper.GradleWrapperMain\nset CLASSPATH=%DIRNAME%\\gradle\\wrapper\\gradle-wrapper.jar\nset WRAPPER_PROPERTIES=%DIRNAME%\\gradle\\wrapper\\gradle-wrapper.properties\nset JAVA_EXE=%JAVA_HOME%\\bin\\java.exe\n\nset GRADLE_OPTS=%JAVA_OPTS% %GRADLE_OPTS% -Dorg.gradle.wrapper.properties=\"%WRAPPER_PROPERTIES%\"\n\n\"%JAVA_EXE%\" %GRADLE_OPTS% -classpath \"%CLASSPATH%\" %STARTER_MAIN_CLASS% %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\nif not \"%OS%\"==\"Windows_NT\" echo 1 > nul | choice /n /c:1\n\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit \"%ERRORLEVEL%\"\nexit /b \"%ERRORLEVEL%\"\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega"
  },
  {
    "path": "listings/chap17/automation/pom.xml",
    "content": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <groupId>ReGinA</groupId>\n    <artifactId>Chap17</artifactId>\n    <packaging>jar</packaging>\n    <version>1.0</version>\n    <name>Chap17</name>\n    <build>\n        <pluginManagement>\n            <plugins>\n                <plugin>\n                    <groupId>org.codehaus.gmaven</groupId>\n                    <artifactId>gmaven-plugin</artifactId>\n                    <version>${gmaven.version}</version>\n                    <executions>\n                        <execution>\n                            <goals>\n                                <goal>compile</goal>\n                                <goal>testCompile</goal>\n                            </goals>\n                            <configuration>\n                                <!-- 1.8 not yet supported by plugin but 1.7 works\n                                 here so long as we provide explicit version -->\n                                <providerSelection>1.7</providerSelection>\n                            </configuration>\n                        </execution>\n                    </executions>\n                    <dependencies>\n                        <dependency>\n                            <groupId>org.codehaus.gmaven.runtime</groupId>\n                            <artifactId>gmaven-runtime-1.7</artifactId>\n                            <version>1.3</version>\n                            <exclusions>\n                                <exclusion>\n                                    <groupId>org.codehaus.groovy</groupId>\n                                    <artifactId>groovy-all</artifactId>\n                                </exclusion>\n                            </exclusions>\n                        </dependency>\n                        <dependency>\n                            <groupId>org.codehaus.groovy</groupId>\n                            <artifactId>groovy-all</artifactId>\n                            <version>${groovy.version}</version>\n                            <scope>compile</scope>\n                        </dependency>\n                    </dependencies>\n                </plugin>\n            </plugins>\n        </pluginManagement>\n        <plugins>\n            <plugin>\n                <groupId>org.codehaus.gmaven</groupId>\n                <artifactId>gmaven-plugin</artifactId>\n                <version>1.3</version>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-compiler-plugin</artifactId>\n                <version>2.3.2</version>\n                <configuration>\n                    <source>1.5</source>\n                    <target>1.5</target>\n                </configuration>\n            </plugin>\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-surefire-plugin</artifactId>\n                <version>2.8</version>\n<!--\n                <configuration>\n                    <includes>\n                        <include>**/*TestNG*</include>\n                    </includes>\n                    <properties>\n                        <property>\n                            <name>junit</name>\n                            <value>false</value>\n                        </property>\n                    </properties>\n                </configuration>\n-->\n                <dependencies>\n                    <dependency>\n                        <groupId>org.apache.maven.surefire</groupId>\n                        <artifactId>surefire-junit47</artifactId>\n                        <version>2.8</version>\n                    </dependency>\n<!--\n                    <dependency>\n                        <groupId>org.apache.maven.surefire</groupId>\n                        <artifactId>surefire-testng</artifactId>\n                        <version>2.8</version>\n                    </dependency>\n-->\n                </dependencies>\n<!--\n                <executions>\n                    <execution>\n                        <phase>test</phase>\n                        <goals>\n                            <goal>test</goal>\n                        </goals>\n                        <configuration>\n                            <testNGArtifactName>none:none</testNGArtifactName>\n                            <excludes>\n                                <exclude>**/*TestNG*</exclude>\n                                <exclude>**/*Suite*</exclude>\n                            </excludes>\n                        </configuration>\n                    </execution>\n                    <execution>\n                        <id>test-testng</id>\n                        <phase>test</phase>\n                        <goals>\n                            <goal>test</goal>\n                        </goals>\n                        <configuration>\n                            <junitArtifactName>none:none</junitArtifactName>\n                            <includes>\n                                <include>**/*TestNG*</include>\n                            </includes>\n                        </configuration>\n                    </execution>\n                </executions>\n-->\n            </plugin>\n        </plugins>\n    </build>\n    <dependencies>\n        <dependency>\n            <groupId>junit</groupId>\n            <artifactId>junit</artifactId>\n            <version>4.8.2</version>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.testng</groupId>\n            <artifactId>testng</artifactId>\n            <version>6.0.1</version>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.codehaus.groovy</groupId>\n            <artifactId>groovy-all</artifactId>\n            <version>${groovy.version}</version>\n            <scope>test</scope>\n        </dependency>\n    </dependencies>\n    <properties>\n        <gmaven.version>1.3</gmaven.version>\n        <!--<groovy.version>1.7.10</groovy.version>-->\n        <groovy.version>1.8.0-rc-3</groovy.version>\n    </properties>\n</project>\n"
  },
  {
    "path": "listings/chap17/automation/src/main/groovy/Calculator.groovy",
    "content": "class Calculator {\n    def add(number1, number2) {\n        return number1 + number2\n    }\n}\n"
  },
  {
    "path": "listings/chap17/automation/src/test/groovy/CalculatorTest.groovy",
    "content": "import org.junit.Test\n\nclass CalculatorTest {\n    @Test\n    void testAdd() {\n        def calculator = new Calculator()\n        assert 10 == calculator.add(3, 7)\n    }\n}\n"
  },
  {
    "path": "listings/chap17/cobertura/build.gradle",
    "content": "plugins {\n  id 'net.saliman.cobertura' version '2.2.6'\n}\n\napply plugin: 'groovy'\n\nrepositories {\n  mavenCentral()\n}\n\ndependencies {\n  compile 'org.codehaus.groovy:groovy-all:2.4.0'\n  testCompile 'junit:junit:4.12'\n}\n"
  },
  {
    "path": "listings/chap17/cobertura/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Thu Apr 10 09:16:15 EST 2014\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=http\\://services.gradle.org/distributions/gradle-2.2.1-bin.zip\n"
  },
  {
    "path": "listings/chap17/cobertura/gradlew",
    "content": "#!/bin/bash\n\n##############################################################################\n##                                                                          ##\n##  Gradle wrapper script for UN*X                                         ##\n##                                                                          ##\n##############################################################################\n\n# Uncomment those lines to set JVM options. GRADLE_OPTS and JAVA_OPTS can be used together.\nGRADLE_OPTS=\"$GRADLE_OPTS -Xmx640m\"\n# JAVA_OPTS=\"$JAVA_OPTS -Xmx512m\"\n\nGRADLE_APP_NAME=Gradle\n\nwarn ( ) {\n    echo \"${PROGNAME}: $*\"\n}\n\ndie ( ) {\n    warn \"$*\"\n    exit 1\n}\n\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set JAVA_HOME if it's not already set.\nif [ -z \"$JAVA_HOME\" ] ; then\n    if $darwin ; then\n        [ -z \"$JAVA_HOME\" -a -d \"/Library/Java/Home\" ] && export JAVA_HOME=\"/Library/Java/Home\"\n        [ -z \"$JAVA_HOME\" -a -d \"/System/Library/Frameworks/JavaVM.framework/Home\" ] && export JAVA_HOME=\"/System/Library/Frameworks/JavaVM.framework/Home\"\n    else\n        javaExecutable=\"`which javac`\"\n        [ -z \"$javaExecutable\" -o \"`expr \\\"$javaExecutable\\\" : '\\([^ ]*\\)'`\" = \"no\" ] && die \"JAVA_HOME not set and cannot find javac to deduce location, please set JAVA_HOME.\"\n        # readlink(1) is not available as standard on Solaris 10.\n        readLink=`which readlink`\n        [ `expr \"$readLink\" : '\\([^ ]*\\)'` = \"no\" ] && die \"JAVA_HOME not set and readlink not available, please set JAVA_HOME.\"\n        javaExecutable=\"`readlink -f \\\"$javaExecutable\\\"`\"\n        javaHome=\"`dirname \\\"$javaExecutable\\\"`\"\n        javaHome=`expr \"$javaHome\" : '\\(.*\\)/bin'`\n        export JAVA_HOME=\"$javaHome\"\n    fi\nfi\n\n# For Cygwin, ensure paths are in UNIX format before anything is touched.\nif $cygwin ; then\n    [ -n \"$JAVACMD\" ] && JAVACMD=`cygpath --unix \"$JAVACMD\"`\n    [ -n \"$JAVA_HOME\" ] && JAVA_HOME=`cygpath --unix \"$JAVA_HOME\"`\nfi\n\nSTARTER_MAIN_CLASS=org.gradle.wrapper.GradleWrapperMain\nCLASSPATH=`dirname \"$0\"`/gradle/wrapper/gradle-wrapper.jar\nWRAPPER_PROPERTIES=`dirname \"$0\"`/gradle/wrapper/gradle-wrapper.properties\n# Determine the Java command to use to start the JVM.\nif [ -z \"$JAVACMD\" ] ; then\n    if [ -n \"$JAVA_HOME\" ] ; then\n        if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n            # IBM's JDK on AIX uses strange locations for the executables\n            JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n        else\n            JAVACMD=\"$JAVA_HOME/bin/java\"\n        fi\n    else\n        JAVACMD=\"java\"\n    fi\nfi\nif [ ! -x \"$JAVACMD\" ] ; then\n    die \"JAVA_HOME is not defined correctly, can not execute: $JAVACMD\"\nfi\nif [ -z \"$JAVA_HOME\" ] ; then\n    warn \"JAVA_HOME environment variable is not set\"\nfi\n\n# For Darwin, add GRADLE_APP_NAME to the JAVA_OPTS as -Xdock:name\nif $darwin; then\n    JAVA_OPTS=\"$JAVA_OPTS -Xdock:name=$GRADLE_APP_NAME\"\n# we may also want to set -Xdock:image\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    JAVA_HOME=`cygpath --path --mixed \"$JAVA_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done \n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\nGRADLE_APP_BASE_NAME=`basename \"$0\"`\n\n\"$JAVACMD\" $JAVA_OPTS $GRADLE_OPTS \\\n        -classpath \"$CLASSPATH\" \\\n        -Dorg.gradle.appname=\"$GRADLE_APP_BASE_NAME\" \\\n        -Dorg.gradle.wrapper.properties=\"$WRAPPER_PROPERTIES\" \\\n        $STARTER_MAIN_CLASS \\\n        \"$@\"\n"
  },
  {
    "path": "listings/chap17/cobertura/gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem                                                                         ##\n@rem  Gradle startup script for Windows                                      ##\n@rem                                                                         ##\n@rem ##########################################################################\n\n@rem\n@rem $Revision: 10602 $ $Date: 2008-01-25 02:49:54 +0100 (ven., 25 janv. 2008) $\n@rem\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Uncomment those lines to set JVM options. GRADLE_OPTS and JAVA_OPTS can be used together.\n@rem set GRADLE_OPTS=%GRADLE_OPTS% -Xmx512m\n@rem set JAVA_OPTS=%JAVA_OPTS% -Xmx512m\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\\\n\n@rem Determine the command interpreter to execute the \"CD\" later\nset COMMAND_COM=\"cmd.exe\"\nif exist \"%SystemRoot%\\system32\\cmd.exe\" set COMMAND_COM=\"%SystemRoot%\\system32\\cmd.exe\"\nif exist \"%SystemRoot%\\command.com\" set COMMAND_COM=\"%SystemRoot%\\command.com\"\n\n@rem Use explicit find.exe to prevent cygwin and others find.exe from being used\nset FIND_EXE=\"find.exe\"\nif exist \"%SystemRoot%\\system32\\find.exe\" set FIND_EXE=\"%SystemRoot%\\system32\\find.exe\"\nif exist \"%SystemRoot%\\command\\find.exe\" set FIND_EXE=\"%SystemRoot%\\command\\find.exe\"\n\n:check_JAVA_HOME\n@rem Make sure we have a valid JAVA_HOME\nif not \"%JAVA_HOME%\" == \"\" goto have_JAVA_HOME\n\necho.\necho ERROR: Environment variable JAVA_HOME has not been set.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\necho.\ngoto end\n\n:have_JAVA_HOME\n@rem Validate JAVA_HOME\n%COMMAND_COM% /C DIR \"%JAVA_HOME%\" 2>&1 | %FIND_EXE% /I /C \"%JAVA_HOME%\" >nul\nif not errorlevel 1 goto init\n\necho.\necho ERROR: JAVA_HOME might be set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation if there are problems.\necho.\n\n:init\n@rem get name of script to launch with full path\n@rem Get command-line arguments, handling Windowz variants\nSET _marker=%JAVA_HOME: =%\n@rem IF NOT \"%_marker%\" == \"%JAVA_HOME%\" ECHO JAVA_HOME \"%JAVA_HOME%\" contains spaces. Please change to a location without spaces if this causes problems.\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%eval[2+2]\" == \"4\" goto 4NT_args\n\nIF \"%_marker%\" == \"%JAVA_HOME%\" goto :win9xME_args\n\nset _FIXPATH=\ncall :fixpath \"%JAVA_HOME%\"\nset JAVA_HOME=%_FIXPATH:~1%\n\ngoto win9xME_args\n\n:fixpath\nif not %1.==. (\nfor /f \"tokens=1* delims=;\" %%a in (%1) do (\ncall :shortfilename \"%%a\" & call :fixpath \"%%b\"\n)\n)\ngoto :EOF\n:shortfilename\nfor %%i in (%1) do set _FIXPATH=%_FIXPATH%;%%~fsi\ngoto :EOF\n\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset STARTER_MAIN_CLASS=org.gradle.wrapper.GradleWrapperMain\nset CLASSPATH=%DIRNAME%\\gradle\\wrapper\\gradle-wrapper.jar\nset WRAPPER_PROPERTIES=%DIRNAME%\\gradle\\wrapper\\gradle-wrapper.properties\nset JAVA_EXE=%JAVA_HOME%\\bin\\java.exe\n\nset GRADLE_OPTS=%JAVA_OPTS% %GRADLE_OPTS% -Dorg.gradle.wrapper.properties=\"%WRAPPER_PROPERTIES%\"\n\n\"%JAVA_EXE%\" %GRADLE_OPTS% -classpath \"%CLASSPATH%\" %STARTER_MAIN_CLASS% %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\nif not \"%OS%\"==\"Windows_NT\" echo 1 > nul | choice /n /c:1\n\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit \"%ERRORLEVEL%\"\nexit /b \"%ERRORLEVEL%\"\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega"
  },
  {
    "path": "listings/chap17/cobertura/src/main/groovy/BiggestPairCalc.groovy",
    "content": "class BiggestPairCalc {\n  int sumBiggestPair(a, b, c) {\n    def op1 = a\n    def op2 = b\n    if (c > a) {\n      op1 = c\n    } else if (c > b) {\n      op2 = c\n    }\n    return op1 + op2\n  }\n}\n"
  },
  {
    "path": "listings/chap17/cobertura/src/main/groovy/BiggestPairCalcFixed.groovy",
    "content": "class BiggestPairCalcFixed {\n  int sumBiggestPair(int a, int b, int c) {\n    def op1 = a\n    def op2 = b\n    if (c > [a, b].min()) {\n      op1 = c\n      op2 = [a, b].max()\n    }\n    return op1 + op2\n  }\n}\n"
  },
  {
    "path": "listings/chap17/cobertura/src/test/groovy/BiggestPairCalcTest.groovy",
    "content": "class BiggestPairCalcTest extends GroovyTestCase {\n  void testSumBiggestPair() {\n    def calc = new BiggestPairCalc()\n    testCalc(calc)\n\n//    def fixed = new BiggestPairCalcFixed()\n//    testCalc(fixed)\n//    assertEquals(11, fixed.sumBiggestPair(5, 2, 6))\n//    assertEquals(15, fixed.sumBiggestPair(5, 9, 6))\n//    assertEquals(16, fixed.sumBiggestPair(10, 2, 6))\n  }\n\n  private void testCalc(calc) {\n    assertEquals(9, calc.sumBiggestPair(5, 4, 1))\n\n    assertEquals(15, calc.sumBiggestPair(5, 9, 6))\n    assertEquals(16, calc.sumBiggestPair(10, 2, 6))\n\n    //assertEquals(11, calc.sumBiggestPair(5, 2, 6))\n  }\n}\n"
  },
  {
    "path": "listings/chap17/extra_ParameterizedTestNG.groovy",
    "content": "@Grab('org.codehaus.groovy:groovy-testng:2.4.0')\n@Grab('com.google.code.guice:guice:1.0')\n@GrabConfig(systemClassLoader = true)\nimport org.testng.annotations.DataProvider\nimport org.testng.annotations.Test\nimport static Converter.celsius\n\nclass extra_ParameterizedTestNG {\n\n  Object[][] scenarios = [\n      [  0,  32, 'Freezing'],\n      [ 20,  68, 'Garden party conditions'],\n      [ 35,  95, 'Beach conditions'],\n      [100, 212, 'Boiling']\n  ]\n\n  @DataProvider(name = 'scenarios')\n  Object[][] scenarios() { scenarios }\n\n  @Test(dataProvider = 'scenarios')\n  void convert(c, f, scenario) {\n    def actual = celsius(f)\n    def msg = \"$scenario: $fºF should convert into $cºC\"\n    assert c == actual, msg\n  }\n}\n"
  },
  {
    "path": "listings/chap17/extra_TestNG.groovy",
    "content": "@Grab('org.codehaus.groovy:groovy-testng:2.4.0')\n@Grab('com.google.code.guice:guice:1.0')\n@GrabConfig(systemClassLoader=true)\nimport org.testng.annotations.Test\n\nclass extra_TestNG {\n  @Test\n  void shouldAdd() {\n    assert 2 == 1 + 1\n  }\n}\n"
  },
  {
    "path": "listings/chap17/snippet1701_JUnit4.groovy",
    "content": "import org.junit.Test\nimport static org.junit.Assert.assertEquals\nclass SimpleJUnit4Test {\n  @Test\n  void shouldAdd() {\n    assertEquals(\"Groovy should add correctly\", 2, 1 + 1)\n  }\n}\n"
  },
  {
    "path": "listings/chap17/snippet1704_listPropertyCheck.groovy",
    "content": "@Grab('net.java.quickcheck:quickcheck:0.6')\nimport static net.java.quickcheck.generator.PrimitiveGenerators.*\nimport static net.java.quickcheck.generator.CombinedGeneratorsIterables.*\n\nfor (words in someNonEmptyLists(strings())) {\n  assert words*.size().sum() == words.sum().size()\n}\n"
  },
  {
    "path": "listings/chap17/test-output/Command line suite/Command line test.html",
    "content": "<html>\n<head>\n<title>TestNG:  Command line test</title>\n<link href=\"../testng.css\" rel=\"stylesheet\" type=\"text/css\" />\n<link href=\"../my-testng.css\" rel=\"stylesheet\" type=\"text/css\" />\n\n<style type=\"text/css\">\n.log { display: none;} \n.stack-trace { display: none;} \n</style>\n<script type=\"text/javascript\">\n<!--\nfunction flip(e) {\n  current = e.style.display;\n  if (current == 'block') {\n    e.style.display = 'none';\n    return 0;\n  }\n  else {\n    e.style.display = 'block';\n    return 1;\n  }\n}\n\nfunction toggleBox(szDivId, elem, msg1, msg2)\n{\n  var res = -1;  if (document.getElementById) {\n    res = flip(document.getElementById(szDivId));\n  }\n  else if (document.all) {\n    // this is the way old msie versions work\n    res = flip(document.all[szDivId]);\n  }\n  if(elem) {\n    if(res == 0) elem.innerHTML = msg1; else elem.innerHTML = msg2;\n  }\n\n}\n\nfunction toggleAllBoxes() {\n  if (document.getElementsByTagName) {\n    d = document.getElementsByTagName('div');\n    for (i = 0; i < d.length; i++) {\n      if (d[i].className == 'log') {\n        flip(d[i]);\n      }\n    }\n  }\n}\n\n// -->\n</script>\n\n</head>\n<body>\n<h2 align='center'>Command line test</h2><table border='1' align=\"center\">\n<tr>\n<td>Tests passed/Failed/Skipped:</td><td>1/0/0</td>\n</tr><tr>\n<td>Started on:</td><td>Thu Jun 04 12:16:31 CEST 2015</td>\n</tr>\n<tr><td>Total time:</td><td>0 seconds (2 ms)</td>\n</tr><tr>\n<td>Included groups:</td><td></td>\n</tr><tr>\n<td>Excluded groups:</td><td></td>\n</tr>\n</table><p/>\n<small><i>(Hover the method name to see the test class name)</i></small><p/>\n<table width='100%' border='1' class='invocation-passed'>\n<tr><td colspan='4' align='center'><b>PASSED TESTS</b></td></tr>\n<tr><td><b>Test method</b></td>\n<td width=\"30%\"><b>Exception</b></td>\n<td width=\"10%\"><b>Time (seconds)</b></td>\n<td><b>Instance</b></td>\n</tr>\n<tr>\n<td title='extra_TestNG.shouldAdd()'><b>shouldAdd</b><br>Test class: extra_TestNG</td>\n<td></td>\n<td>0</td>\n<td>extra_TestNG@2ec2a43e</td></tr>\n</table><p>\n</body>\n</html>"
  },
  {
    "path": "listings/chap17/test-output/Command line suite/Command line test.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!-- Generated by org.testng.reporters.JUnitXMLReporter -->\n<testsuite hostname=\"Dierk-Konigs-MacBook-Pro.local\" tests=\"1\" failures=\"0\" timestamp=\"4 Jun 2015 10:16:31 GMT\" time=\"0.002\" errors=\"0\">\n  <testcase name=\"shouldAdd\" time=\"0.001\" classname=\"extra_TestNG\"/>\n</testsuite>\n"
  },
  {
    "path": "listings/chap17/test-output/emailable-report.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\"><head><title>TestNG Report</title><style type=\"text/css\">table {margin-bottom:10px;border-collapse:collapse;empty-cells:show}th,td {border:1px solid #009;padding:.25em .5em}th {vertical-align:bottom}td {vertical-align:top}table a {font-weight:bold}.stripe td {background-color: #E6EBF9}.num {text-align:right}.passedodd td {background-color: #3F3}.passedeven td {background-color: #0A0}.skippedodd td {background-color: #DDD}.skippedeven td {background-color: #CCC}.failedodd td,.attn {background-color: #F33}.failedeven td,.stripe .attn {background-color: #D00}.stacktrace {white-space:pre;font-family:monospace}.totop {font-size:85%;text-align:center;border-bottom:2px solid #000}</style></head><body><table><tr><th>Test</th><th># Passed</th><th># Skipped</th><th># Failed</th><th>Time (ms)</th><th>Included Groups</th><th>Excluded Groups</th></tr><tr><th colspan=\"7\">Command line suite</th></tr><tr><td><a href=\"#t0\">Command line test</a></td><td class=\"num\">1</td><td class=\"num\">0</td><td class=\"num\">0</td><td class=\"num\">2</td><td></td><td></td></tr></table><table><thead><tr><th>Class</th><th>Method</th><th>Start</th><th>Time (ms)</th></tr></thead><tbody><tr><th colspan=\"4\">Command line suite</th></tr></tbody><tbody id=\"t0\"><tr><th colspan=\"4\">Command line test &#8212; passed</th></tr><tr class=\"passedeven\"><td rowspan=\"1\">extra_TestNG</td><td><a href=\"#m0\">shouldAdd</a></td><td rowspan=\"1\">1433412991056</td><td rowspan=\"1\">1</td></tr></tbody></table><h2>Command line test</h2><h3 id=\"m0\">extra_TestNG#shouldAdd</h3><table class=\"result\"></table><p class=\"totop\"><a href=\"#summary\">back to summary</a></p></body></html>"
  },
  {
    "path": "listings/chap17/test-output/index.html",
    "content": "<!DOCTYPE html>\n\n<html>\n  <head>\n  <title>TestNG reports</title>\n\n    <link type=\"text/css\" href=\"testng-reports.css\" rel=\"stylesheet\" />  \n    <script type=\"text/javascript\" src=\"jquery-1.7.1.min.js\"></script>\n    <script type=\"text/javascript\" src=\"testng-reports.js\"></script>\n    <script type=\"text/javascript\" src=\"https://www.google.com/jsapi\"></script>\n    <script type='text/javascript'>\n      google.load('visualization', '1', {packages:['table']});\n      google.setOnLoadCallback(drawTable);\n      var suiteTableInitFunctions = new Array();\n      var suiteTableData = new Array();\n    </script>\n    <!--\n      <script type=\"text/javascript\" src=\"jquery-ui/js/jquery-ui-1.8.16.custom.min.js\"></script>\n     -->\n  </head>\n\n  <body>\n    <div class=\"top-banner-root\">\n      <span class=\"top-banner-title-font\">Test results</span>\n      <br/>\n      <span class=\"top-banner-font-1\">1 suite</span>\n    </div> <!-- top-banner-root -->\n    <div class=\"navigator-root\">\n      <div class=\"navigator-suite-header\">\n        <span>All suites</span>\n        <a href=\"#\" class=\"collapse-all-link\" title=\"Collapse/expand all the suites\">\n          <img class=\"collapse-all-icon\" src=\"collapseall.gif\">\n          </img> <!-- collapse-all-icon -->\n        </a> <!-- collapse-all-link -->\n      </div> <!-- navigator-suite-header -->\n      <div class=\"suite\">\n        <div class=\"rounded-window\">\n          <div class=\"suite-header light-rounded-window-top\">\n            <a href=\"#\" class=\"navigator-link\" panel-name=\"suite-Command_line_suite\">\n              <span class=\"suite-name border-passed\">Command line suite</span>\n            </a> <!-- navigator-link -->\n          </div> <!-- suite-header light-rounded-window-top -->\n          <div class=\"navigator-suite-content\">\n            <div class=\"suite-section-title\">\n              <span>Info</span>\n            </div> <!-- suite-section-title -->\n            <div class=\"suite-section-content\">\n              <ul>\n                <li>\n                  <a href=\"#\" class=\"navigator-link \" panel-name=\"test-xml-Command_line_suite\">\n                    <span>[unset file name]</span>\n                  </a> <!-- navigator-link  -->\n                </li>\n                <li>\n                  <a href=\"#\" class=\"navigator-link \" panel-name=\"testlist-Command_line_suite\">\n                    <span class=\"test-stats\">1 test</span>\n                  </a> <!-- navigator-link  -->\n                </li>\n                <li>\n                  <a href=\"#\" class=\"navigator-link \" panel-name=\"group-Command_line_suite\">\n                    <span>0 groups</span>\n                  </a> <!-- navigator-link  -->\n                </li>\n                <li>\n                  <a href=\"#\" class=\"navigator-link \" panel-name=\"times-Command_line_suite\">\n                    <span>Times</span>\n                  </a> <!-- navigator-link  -->\n                </li>\n                <li>\n                  <a href=\"#\" class=\"navigator-link \" panel-name=\"reporter-Command_line_suite\">\n                    <span>Reporter output</span>\n                  </a> <!-- navigator-link  -->\n                </li>\n                <li>\n                  <a href=\"#\" class=\"navigator-link \" panel-name=\"ignored-methods-Command_line_suite\">\n                    <span>Ignored methods</span>\n                  </a> <!-- navigator-link  -->\n                </li>\n                <li>\n                  <a href=\"#\" class=\"navigator-link \" panel-name=\"chronological-Command_line_suite\">\n                    <span>Chronological view</span>\n                  </a> <!-- navigator-link  -->\n                </li>\n              </ul>\n            </div> <!-- suite-section-content -->\n            <div class=\"result-section\">\n              <div class=\"suite-section-title\">\n                <span>Results</span>\n              </div> <!-- suite-section-title -->\n              <div class=\"suite-section-content\">\n                <ul>\n                  <li>\n                    <span class=\"method-stats\">1 method,   1 passed</span>\n                  </li>\n                  <li>\n                    <span class=\"method-list-title passed\">Passed methods</span>\n                    <span class=\"show-or-hide-methods passed\">\n                      <a href=\"#\" panel-name=\"suite-Command_line_suite\" class=\"hide-methods passed suite-Command_line_suite\"> (hide)</a> <!-- hide-methods passed suite-Command_line_suite -->\n                      <a href=\"#\" panel-name=\"suite-Command_line_suite\" class=\"show-methods passed suite-Command_line_suite\"> (show)</a> <!-- show-methods passed suite-Command_line_suite -->\n                    </span>\n                    <div class=\"method-list-content passed suite-Command_line_suite\">\n                      <span>\n                        <img width=\"3%\" src=\"passed.png\"/>\n                        <a href=\"#\" class=\"method navigator-link\" panel-name=\"suite-Command_line_suite\" title=\"extra_TestNG\" hash-for-method=\"shouldAdd\">shouldAdd</a> <!-- method navigator-link -->\n                      </span>\n                      <br/>\n                    </div> <!-- method-list-content passed suite-Command_line_suite -->\n                  </li>\n                </ul>\n              </div> <!-- suite-section-content -->\n            </div> <!-- result-section -->\n          </div> <!-- navigator-suite-content -->\n        </div> <!-- rounded-window -->\n      </div> <!-- suite -->\n    </div> <!-- navigator-root -->\n    <div class=\"wrapper\">\n      <div class=\"main-panel-root\">\n        <div panel-name=\"suite-Command_line_suite\" class=\"panel Command_line_suite\">\n          <div class=\"suite-Command_line_suite-class-passed\">\n            <div class=\"main-panel-header rounded-window-top\">\n              <img src=\"passed.png\"/>\n              <span class=\"class-name\">extra_TestNG</span>\n            </div> <!-- main-panel-header rounded-window-top -->\n            <div class=\"main-panel-content rounded-window-bottom\">\n              <div class=\"method\">\n                <div class=\"method-content\">\n                  <a name=\"shouldAdd\">\n                  </a> <!-- shouldAdd -->\n                  <span class=\"method-name\">shouldAdd</span>\n                </div> <!-- method-content -->\n              </div> <!-- method -->\n            </div> <!-- main-panel-content rounded-window-bottom -->\n          </div> <!-- suite-Command_line_suite-class-passed -->\n        </div> <!-- panel Command_line_suite -->\n        <div panel-name=\"test-xml-Command_line_suite\" class=\"panel\">\n          <div class=\"main-panel-header rounded-window-top\">\n          </div> <!-- main-panel-header rounded-window-top -->\n          <div class=\"main-panel-content rounded-window-bottom\">\n            <pre>\n&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;\n&lt;!DOCTYPE suite SYSTEM &quot;http://testng.org/testng-1.0.dtd&quot;&gt;\n&lt;suite name=&quot;Command line suite&quot;&gt;\n  &lt;test name=&quot;Command line test&quot; preserve-order=&quot;false&quot;&gt;\n    &lt;classes&gt;\n      &lt;class name=&quot;extra_TestNG&quot;/&gt;\n    &lt;/classes&gt;\n  &lt;/test&gt; &lt;!-- Command line test --&gt;\n&lt;/suite&gt; &lt;!-- Command line suite --&gt;\n            </pre>\n          </div> <!-- main-panel-content rounded-window-bottom -->\n        </div> <!-- panel -->\n        <div panel-name=\"testlist-Command_line_suite\" class=\"panel\">\n          <div class=\"main-panel-header rounded-window-top\">\n            <span class=\"header-content\">Tests for Command line suite</span>\n          </div> <!-- main-panel-header rounded-window-top -->\n          <div class=\"main-panel-content rounded-window-bottom\">\n            <ul>\n              <li>\n                <span class=\"test-name\">Command line test (1 class)</span>\n              </li>\n            </ul>\n          </div> <!-- main-panel-content rounded-window-bottom -->\n        </div> <!-- panel -->\n        <div panel-name=\"group-Command_line_suite\" class=\"panel\">\n          <div class=\"main-panel-header rounded-window-top\">\n            <span class=\"header-content\">Groups for Command line suite</span>\n          </div> <!-- main-panel-header rounded-window-top -->\n          <div class=\"main-panel-content rounded-window-bottom\">\n          </div> <!-- main-panel-content rounded-window-bottom -->\n        </div> <!-- panel -->\n        <div panel-name=\"times-Command_line_suite\" class=\"panel\">\n          <div class=\"main-panel-header rounded-window-top\">\n            <span class=\"header-content\">Times for Command line suite</span>\n          </div> <!-- main-panel-header rounded-window-top -->\n          <div class=\"main-panel-content rounded-window-bottom\">\n            <div class=\"times-div\">\n              <script type=\"text/javascript\">\nsuiteTableInitFunctions.push('tableData_Command_line_suite');\nfunction tableData_Command_line_suite() {\nvar data = new google.visualization.DataTable();\ndata.addColumn('number', 'Number');\ndata.addColumn('string', 'Method');\ndata.addColumn('string', 'Class');\ndata.addColumn('number', 'Time (ms)');\ndata.addRows(1);\ndata.setCell(0, 0, 0)\ndata.setCell(0, 1, 'shouldAdd')\ndata.setCell(0, 2, 'extra_TestNG')\ndata.setCell(0, 3, 1);\nwindow.suiteTableData['Command_line_suite']= { tableData: data, tableDiv: 'times-div-Command_line_suite'}\nreturn data;\n}\n              </script>\n              <span class=\"suite-total-time\">Total running time: 1 ms</span>\n              <div id=\"times-div-Command_line_suite\">\n              </div> <!-- times-div-Command_line_suite -->\n            </div> <!-- times-div -->\n          </div> <!-- main-panel-content rounded-window-bottom -->\n        </div> <!-- panel -->\n        <div panel-name=\"reporter-Command_line_suite\" class=\"panel\">\n          <div class=\"main-panel-header rounded-window-top\">\n            <span class=\"header-content\">Reporter output for Command line suite</span>\n          </div> <!-- main-panel-header rounded-window-top -->\n          <div class=\"main-panel-content rounded-window-bottom\">\n          </div> <!-- main-panel-content rounded-window-bottom -->\n        </div> <!-- panel -->\n        <div panel-name=\"ignored-methods-Command_line_suite\" class=\"panel\">\n          <div class=\"main-panel-header rounded-window-top\">\n            <span class=\"header-content\">0 ignored methods</span>\n          </div> <!-- main-panel-header rounded-window-top -->\n          <div class=\"main-panel-content rounded-window-bottom\">\n          </div> <!-- main-panel-content rounded-window-bottom -->\n        </div> <!-- panel -->\n        <div panel-name=\"chronological-Command_line_suite\" class=\"panel\">\n          <div class=\"main-panel-header rounded-window-top\">\n            <span class=\"header-content\">Methods in chronological order</span>\n          </div> <!-- main-panel-header rounded-window-top -->\n          <div class=\"main-panel-content rounded-window-bottom\">\n            <div class=\"chronological-class\">\n              <div class=\"chronological-class-name\">extra_TestNG</div> <!-- chronological-class-name -->\n              <div class=\"test-method\">\n                <span class=\"method-name\">shouldAdd</span>\n                <span class=\"method-start\">0 ms</span>\n              </div> <!-- test-method -->\n          </div> <!-- main-panel-content rounded-window-bottom -->\n        </div> <!-- panel -->\n      </div> <!-- main-panel-root -->\n    </div> <!-- wrapper -->\n  </body>\n</html>\n"
  },
  {
    "path": "listings/chap17/test-output/junitreports/TEST-extra_ParameterizedTestNG.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!-- Generated by org.testng.reporters.JUnitReportReporter -->\n<testsuite hostname=\"Dierk-Konigs-MacBook-Pro.local\" name=\"extra_ParameterizedTestNG\" tests=\"4\" failures=\"0\" timestamp=\"4 Jun 2015 10:16:30 GMT\" time=\"0.011\" errors=\"0\">\n  <testcase name=\"convert\" time=\"0.001\" classname=\"extra_ParameterizedTestNG\"/>\n  <testcase name=\"convert\" time=\"0.010\" classname=\"extra_ParameterizedTestNG\"/>\n  <testcase name=\"convert\" time=\"0.000\" classname=\"extra_ParameterizedTestNG\"/>\n  <testcase name=\"convert\" time=\"0.000\" classname=\"extra_ParameterizedTestNG\"/>\n</testsuite> <!-- extra_ParameterizedTestNG -->\n"
  },
  {
    "path": "listings/chap17/test-output/junitreports/TEST-extra_TestNG.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!-- Generated by org.testng.reporters.JUnitReportReporter -->\n<testsuite hostname=\"Dierk-Konigs-MacBook-Pro.local\" name=\"extra_TestNG\" tests=\"1\" failures=\"0\" timestamp=\"4 Jun 2015 10:16:31 GMT\" time=\"0.001\" errors=\"0\">\n  <testcase name=\"shouldAdd\" time=\"0.001\" classname=\"extra_TestNG\"/>\n</testsuite> <!-- extra_TestNG -->\n"
  },
  {
    "path": "listings/chap17/test-output/old/Command line suite/Command line test.properties",
    "content": "[SuiteResult context=Command line test]"
  },
  {
    "path": "listings/chap17/test-output/old/Command line suite/classes.html",
    "content": "<table border='1'>\n<tr>\n<th>Class name</th>\n<th>Method name</th>\n<th>Groups</th>\n</tr><tr>\n<td>extra_TestNG</td>\n<td>&nbsp;</td><td>&nbsp;</td></tr>\n<tr>\n<td align='center' colspan='3'>@Test</td>\n</tr>\n<tr>\n<td>&nbsp;</td>\n<td>shouldAdd</td>\n<td>&nbsp;</td></tr>\n<tr>\n<td align='center' colspan='3'>@BeforeClass</td>\n</tr>\n<tr>\n<td align='center' colspan='3'>@BeforeMethod</td>\n</tr>\n<tr>\n<td align='center' colspan='3'>@AfterMethod</td>\n</tr>\n<tr>\n<td align='center' colspan='3'>@AfterClass</td>\n</tr>\n</table>\n"
  },
  {
    "path": "listings/chap17/test-output/old/Command line suite/groups.html",
    "content": "<h2>Groups used for this test run</h2>"
  },
  {
    "path": "listings/chap17/test-output/old/Command line suite/index.html",
    "content": "<html><head><title>Results for Command line suite</title></head>\n<frameset cols=\"26%,74%\">\n<frame src=\"toc.html\" name=\"navFrame\">\n<frame src=\"main.html\" name=\"mainFrame\">\n</frameset>\n</html>\n"
  },
  {
    "path": "listings/chap17/test-output/old/Command line suite/main.html",
    "content": "<html><head><title>Results for Command line suite</title></head>\n<body>Select a result on the left-hand pane.</body></html>\n"
  },
  {
    "path": "listings/chap17/test-output/old/Command line suite/methods-alphabetical.html",
    "content": "<h2>Methods run, sorted chronologically</h2><h3>&gt;&gt; means before, &lt;&lt; means after</h3><p/><br/><em>Command line suite</em><p/><small><i>(Hover the method name to see the test class name)</i></small><p/>\n<table border=\"1\">\n<tr><th>Time</th><th>Delta (ms)</th><th>Suite<br>configuration</th><th>Test<br>configuration</th><th>Class<br>configuration</th><th>Groups<br>configuration</th><th>Method<br>configuration</th><th>Test<br>method</th><th>Thread</th><th>Instances</th></tr>\n<tr bgcolor=\"6773c1\">  <td>15/06/04 12:16:31</td>   <td>0</td> <td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td title=\"extra_TestNG.shouldAdd()[pri:0, instance:extra_TestNG@2ec2a43e]\">shouldAdd</td> \n  <td>main@1098448570</td>   <td></td> </tr>\n</table>\n"
  },
  {
    "path": "listings/chap17/test-output/old/Command line suite/methods-not-run.html",
    "content": "<h2>Methods that were not run</h2><table>\n</table>"
  },
  {
    "path": "listings/chap17/test-output/old/Command line suite/methods.html",
    "content": "<h2>Methods run, sorted chronologically</h2><h3>&gt;&gt; means before, &lt;&lt; means after</h3><p/><br/><em>Command line suite</em><p/><small><i>(Hover the method name to see the test class name)</i></small><p/>\n<table border=\"1\">\n<tr><th>Time</th><th>Delta (ms)</th><th>Suite<br>configuration</th><th>Test<br>configuration</th><th>Class<br>configuration</th><th>Groups<br>configuration</th><th>Method<br>configuration</th><th>Test<br>method</th><th>Thread</th><th>Instances</th></tr>\n<tr bgcolor=\"6773c1\">  <td>15/06/04 12:16:31</td>   <td>0</td> <td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td title=\"extra_TestNG.shouldAdd()[pri:0, instance:extra_TestNG@2ec2a43e]\">shouldAdd</td> \n  <td>main@1098448570</td>   <td></td> </tr>\n</table>\n"
  },
  {
    "path": "listings/chap17/test-output/old/Command line suite/reporter-output.html",
    "content": "<h2>Reporter output</h2><table></table>"
  },
  {
    "path": "listings/chap17/test-output/old/Command line suite/testng.xml.html",
    "content": "<html><head><title>testng.xml for Command line suite</title></head><body><tt>&lt;?xml&nbsp;version=\"1.0\"&nbsp;encoding=\"UTF-8\"?&gt;<br/>&lt;!DOCTYPE&nbsp;suite&nbsp;SYSTEM&nbsp;\"http://testng.org/testng-1.0.dtd\"&gt;<br/>&lt;suite&nbsp;name=\"Command&nbsp;line&nbsp;suite\"&gt;<br/>&nbsp;&nbsp;&lt;test&nbsp;name=\"Command&nbsp;line&nbsp;test\"&nbsp;preserve-order=\"false\"&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;classes&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;class&nbsp;name=\"extra_TestNG\"/&gt;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/classes&gt;<br/>&nbsp;&nbsp;&lt;/test&gt;&nbsp;&lt;!--&nbsp;Command&nbsp;line&nbsp;test&nbsp;--&gt;<br/>&lt;/suite&gt;&nbsp;&lt;!--&nbsp;Command&nbsp;line&nbsp;suite&nbsp;--&gt;<br/></tt></body></html>"
  },
  {
    "path": "listings/chap17/test-output/old/Command line suite/toc.html",
    "content": "<html>\n<head>\n<title>Results for Command line suite</title>\n<link href=\"../testng.css\" rel=\"stylesheet\" type=\"text/css\" />\n<link href=\"../my-testng.css\" rel=\"stylesheet\" type=\"text/css\" />\n</head>\n<body>\n<h3><p align=\"center\">Results for<br/><em>Command line suite</em></p></h3>\n<table border='1' width='100%'>\n<tr valign='top'>\n<td>1 test</td>\n<td><a target='mainFrame' href='classes.html'>1 class</a></td>\n<td>1 method:<br/>\n&nbsp;&nbsp;<a target='mainFrame' href='methods.html'>chronological</a><br/>\n&nbsp;&nbsp;<a target='mainFrame' href='methods-alphabetical.html'>alphabetical</a><br/>\n&nbsp;&nbsp;<a target='mainFrame' href='methods-not-run.html'>not run (0)</a></td>\n</tr>\n<tr>\n<td><a target='mainFrame' href='groups.html'>0 group</a></td>\n<td><a target='mainFrame' href='reporter-output.html'>reporter output</a></td>\n<td><a target='mainFrame' href='testng.xml.html'>testng.xml</a></td>\n</tr></table>\n<table width='100%' class='test-passed'>\n<tr><td>\n<table style='width: 100%'><tr><td valign='top'>Command line test (1/0/0)</td><td valign='top' align='right'>\n  <a href='Command line test.html' target='mainFrame'>Results</a>\n</td></tr></table>\n</td></tr><p/>\n</table>\n</body></html>"
  },
  {
    "path": "listings/chap17/test-output/old/index.html",
    "content": "<html>\n<head><title>Test results</title><link href=\"./testng.css\" rel=\"stylesheet\" type=\"text/css\" />\n<link href=\"./my-testng.css\" rel=\"stylesheet\" type=\"text/css\" />\n</head><body>\n<h2><p align='center'>Test results</p></h2>\n<table border='1' width='100%' class='main-page'><tr><th>Suite</th><th>Passed</th><th>Failed</th><th>Skipped</th><th>testng.xml</th></tr>\n<tr align='center' class='invocation-passed'><td><em>Total</em></td><td><em>1</em></td><td><em>0</em></td><td><em>0</em></td><td>&nbsp;</td></tr>\n<tr align='center' class='invocation-passed'><td><a href='Command line suite/index.html'>Command line suite</a></td>\n<td>1</td><td>0</td><td>0</td><td><a href='Command line suite/testng.xml.html'>Link</a></td></tr></table></body></html>\n"
  },
  {
    "path": "listings/chap17/test-output/testng-reports.css",
    "content": "body {\n    margin: 0px 0px 5px 5px;\n}\n\nul {\n    margin: 0px;\n}\n\nli {\n    list-style-type: none;\n}\n\na {\n    text-decoration: none;\n}\n\na:hover {\n    text-decoration: underline;\n}\n\n.navigator-selected {\n    background: #ffa500;\n}\n\n.wrapper {\n    position: absolute;\n    top: 60px;\n    bottom: 0;\n    left: 400px;\n    right: 0;\n    overflow: auto;\n}\n\n.navigator-root {\n    position: absolute;\n    top: 60px;\n    bottom: 0;\n    left: 0;\n    width: 400px;\n    overflow-y: auto;\n}\n\n.suite {\n    margin: 0px 10px 10px 0px;\n    background-color: #fff8dc;\n}\n\n.suite-name {\n    padding-left: 10px;\n    font-size: 25px;\n    font-family: Times;\n}\n\n.main-panel-header {\n    padding: 5px;\n    background-color: #9FB4D9; //afeeee;\n    font-family: monospace;\n    font-size: 18px;\n}\n\n.main-panel-content {\n    padding: 5px;\n    margin-bottom: 10px;\n    background-color: #DEE8FC; //d0ffff;\n}\n\n.rounded-window {\n    border-radius: 10px;\n    border-style: solid;\n    border-width: 1px;\n}\n\n.rounded-window-top {\n    border-top-right-radius: 10px 10px;\n    border-top-left-radius: 10px 10px;\n    border-style: solid;\n    border-width: 1px;\n    overflow: auto;\n}\n\n.light-rounded-window-top {\n    border-top-right-radius: 10px 10px;\n    border-top-left-radius: 10px 10px;\n}\n\n.rounded-window-bottom {\n    border-style: solid;\n    border-width: 0px 1px 1px 1px;\n    border-bottom-right-radius: 10px 10px;\n    border-bottom-left-radius: 10px 10px;\n    overflow: auto;\n}\n\n.method-name {\n    font-size: 12px;\n    font-family: monospace;\n}\n\n.method-content {\n    border-style: solid;\n    border-width: 0px 0px 1px 0px;\n    margin-bottom: 10;\n    padding-bottom: 5px;\n    width: 80%;\n}\n\n.parameters {\n    font-size: 14px;\n    font-family: monospace;\n}\n\n.stack-trace {\n    white-space: pre;\n    font-family: monospace;\n    font-size: 12px;\n    font-weight: bold;\n    margin-top: 0px;\n    margin-left: 20px;\n}\n\n.testng-xml {\n    font-family: monospace;\n}\n\n.method-list-content {\n    margin-left: 10px;\n}\n\n.navigator-suite-content {\n    margin-left: 10px;\n    font: 12px 'Lucida Grande';\n}\n\n.suite-section-title {\n    margin-top: 10px;\n    width: 80%;\n    border-style: solid;\n    border-width: 1px 0px 0px 0px;\n    font-family: Times;\n    font-size: 18px;\n    font-weight: bold;\n}\n\n.suite-section-content {\n    list-style-image: url(bullet_point.png);\n}\n\n.top-banner-root {\n    position: absolute;\n    top: 0;\n    height: 45px;\n    left: 0;\n    right: 0;\n    padding: 5px;\n    margin: 0px 0px 5px 0px;\n    background-color: #0066ff;\n    font-family: Times;\n    color: #fff;\n    text-align: center;\n}\n\n.top-banner-title-font {\n    font-size: 25px;\n}\n\n.test-name {\n    font-family: 'Lucida Grande';\n    font-size: 16px;\n}\n\n.suite-icon {\n    padding: 5px;\n    float: right;\n    height: 20;\n}\n\n.test-group {\n    font: 20px 'Lucida Grande';\n    margin: 5px 5px 10px 5px;\n    border-width: 0px 0px 1px 0px;\n    border-style: solid;\n    padding: 5px;\n}\n\n.test-group-name {\n    font-weight: bold;\n}\n\n.method-in-group {\n    font-size: 16px;\n    margin-left: 80px;\n}\n\ntable.google-visualization-table-table {\n    width: 100%;\n}\n\n.reporter-method-name {\n    font-size: 14px;\n    font-family: monospace;\n}\n\n.reporter-method-output-div {\n    padding: 5px;\n    margin: 0px 0px 5px 20px;\n    font-size: 12px;\n    font-family: monospace;\n    border-width: 0px 0px 0px 1px;\n    border-style: solid;\n}\n\n.ignored-class-div {\n    font-size: 14px;\n    font-family: monospace;\n}\n\n.ignored-methods-div {\n    padding: 5px;\n    margin: 0px 0px 5px 20px;\n    font-size: 12px;\n    font-family: monospace;\n    border-width: 0px 0px 0px 1px;\n    border-style: solid;\n}\n\n.border-failed {\n    border-top-left-radius: 10px 10px;\n    border-bottom-left-radius: 10px 10px;\n    border-style: solid;\n    border-width: 0px 0px 0px 10px;\n    border-color: #f00;\n}\n\n.border-skipped {\n    border-top-left-radius: 10px 10px;\n    border-bottom-left-radius: 10px 10px;\n    border-style: solid;\n    border-width: 0px 0px 0px 10px;\n    border-color: #edc600;\n}\n\n.border-passed {\n    border-top-left-radius: 10px 10px;\n    border-bottom-left-radius: 10px 10px;\n    border-style: solid;\n    border-width: 0px 0px 0px 10px;\n    border-color: #19f52d;\n}\n\n.times-div {\n    text-align: center;\n    padding: 5px;\n}\n\n.suite-total-time {\n    font: 16px 'Lucida Grande';\n}\n\n.configuration-suite {\n    margin-left: 20px;\n}\n\n.configuration-test {\n    margin-left: 40px;\n}\n\n.configuration-class {\n    margin-left: 60px;\n}\n\n.configuration-method {\n    margin-left: 80px;\n}\n\n.test-method {\n    margin-left: 100px;\n}\n\n.chronological-class {\n    background-color: #0ccff;\n    border-style: solid;\n    border-width: 0px 0px 1px 1px;\n}\n\n.method-start {\n    float: right;\n}\n\n.chronological-class-name {\n    padding: 0px 0px 0px 5px;\n    color: #008;\n}\n\n.after, .before, .test-method {\n    font-family: monospace;\n    font-size: 14px;\n}\n\n.navigator-suite-header {\n    font-size: 22px;\n    margin: 0px 10px 5px 0px;\n    background-color: #deb887;\n    text-align: center;\n}\n\n.collapse-all-icon {\n    padding: 5px;\n    float: right;\n}\n"
  },
  {
    "path": "listings/chap17/test-output/testng-reports.js",
    "content": "$(document).ready(function() {\n    $('a.navigator-link').click(function() {\n        // Extract the panel for this link\n        var panel = getPanelName($(this));\n\n        // Mark this link as currently selected\n        $('.navigator-link').parent().removeClass('navigator-selected');\n        $(this).parent().addClass('navigator-selected');\n\n        showPanel(panel);\n    });\n\n    installMethodHandlers('failed');\n    installMethodHandlers('skipped');\n    installMethodHandlers('passed', true); // hide passed methods by default\n\n    $('a.method').click(function() {\n        showMethod($(this));\n        return false;\n    });\n\n    // Hide all the panels and display the first one (do this last\n    // to make sure the click() will invoke the listeners)\n    $('.panel').hide();\n    $('.navigator-link').first().click();\n\n    // Collapse/expand the suites\n    $('a.collapse-all-link').click(function() {\n        var contents = $('.navigator-suite-content');\n        if (contents.css('display') == 'none') {\n            contents.show();\n        } else {\n            contents.hide();\n        }\n    });\n});\n\n// The handlers that take care of showing/hiding the methods\nfunction installMethodHandlers(name, hide) {\n    function getContent(t) {\n    return $('.method-list-content.' + name + \".\" + t.attr('panel-name'));\n    }\n\n    function getHideLink(t, name) {\n        var s = 'a.hide-methods.' + name + \".\" + t.attr('panel-name');\n        return $(s);\n    }\n\n    function getShowLink(t, name) {\n        return $('a.show-methods.' + name + \".\" + t.attr('panel-name'));\n    }\n\n    function getMethodPanelClassSel(element, name) {\n        var panelName = getPanelName(element);\n    var sel = '.' + panelName + \"-class-\" + name;\n        return $(sel);\n    }\n\n    $('a.hide-methods.' + name).click(function() {\n        var w = getContent($(this));\n        w.hide();\n        getHideLink($(this), name).hide();\n        getShowLink($(this), name).show();\n    getMethodPanelClassSel($(this), name).hide();\n    });\n\n    $('a.show-methods.' + name).click(function() {\n        var w = getContent($(this));\n        w.show();\n        getHideLink($(this), name).show();\n        getShowLink($(this), name).hide();\n    showPanel(getPanelName($(this)));\n    getMethodPanelClassSel($(this), name).show();\n    });\n\n    if (hide) {\n        $('a.hide-methods.' + name).click();\n    } else {\n        $('a.show-methods.' + name).click();\n    }\n}\n\nfunction getHashForMethod(element) {\n    return element.attr('hash-for-method');\n}\n\nfunction getPanelName(element) {\n    return element.attr('panel-name');\n}\n\nfunction showPanel(panelName) {\n    $('.panel').hide();\n    var panel = $('.panel[panel-name=\"' + panelName + '\"]');\n    panel.show();\n}\n\nfunction showMethod(element) {\n    var hashTag = getHashForMethod(element);\n    var panelName = getPanelName(element);\n    showPanel(panelName);\n    var current = document.location.href;\n    var base = current.substring(0, current.indexOf('#'))\n    document.location.href = base + '#' + hashTag;\n    var newPosition = $(document).scrollTop() - 65;\n    $(document).scrollTop(newPosition);\n}\n\nfunction drawTable() {\n    for (var i = 0; i < suiteTableInitFunctions.length; i++) {\n        window[suiteTableInitFunctions[i]]();\n    }\n\n    for (var k in window.suiteTableData) {\n        var v = window.suiteTableData[k];\n        var div = v.tableDiv;\n        var data = v.tableData\n        var table = new google.visualization.Table(document.getElementById(div));\n        table.draw(data, {\n            showRowNumber : false\n        });\n    }\n}\n"
  },
  {
    "path": "listings/chap17/test-output/testng-results.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<testng-results skipped=\"0\" failed=\"0\" total=\"1\" passed=\"1\">\n  <reporter-output>\n  </reporter-output>\n  <suite name=\"Command line suite\" duration-ms=\"2\" started-at=\"2015-06-04T10:16:31Z\" finished-at=\"2015-06-04T10:16:31Z\">\n    <groups>\n    </groups>\n    <test name=\"Command line test\" duration-ms=\"2\" started-at=\"2015-06-04T10:16:31Z\" finished-at=\"2015-06-04T10:16:31Z\">\n      <class name=\"extra_TestNG\">\n        <test-method status=\"PASS\" signature=\"shouldAdd()[pri:0, instance:extra_TestNG@2ec2a43e]\" name=\"shouldAdd\" duration-ms=\"1\" started-at=\"2015-06-04T12:16:31Z\" finished-at=\"2015-06-04T12:16:31Z\">\n          <reporter-output>\n          </reporter-output>\n        </test-method> <!-- shouldAdd -->\n      </class> <!-- extra_TestNG -->\n    </test> <!-- Command line test -->\n  </suite> <!-- Command line suite -->\n</testng-results>\n"
  },
  {
    "path": "listings/chap17/test-output/testng.css",
    "content": ".invocation-failed,  .test-failed  { background-color: #DD0000; }\n.invocation-percent, .test-percent { background-color: #006600; }\n.invocation-passed,  .test-passed  { background-color: #00AA00; }\n.invocation-skipped, .test-skipped { background-color: #CCCC00; }\n\n.main-page {\n  font-size: x-large;\n}\n\n"
  },
  {
    "path": "listings/chap18/Listing_18_01_ConcurrentSquares.groovy",
    "content": "import static groovyx.gpars.GParsPool.withPool\n\ndef numbers = [1, 2, 3,  4,  5,  6]\ndef squares = [1, 4, 9, 16, 25, 36]\n\nwithPool {\n   assert squares == numbers.collectParallel  { it * it }\n}"
  },
  {
    "path": "listings/chap18/Listing_18_02_ConcurrentSquaresTransparent.groovy",
    "content": "import static groovyx.gpars.GParsPool.withPool\n\ndef numbers = [1, 2, 3,  4,  5,  6]\ndef squares = [1, 4, 9, 16, 25, 36]\n\nwithPool {\n    assertSquares(numbers.makeConcurrent(), squares)\n}\ndef assertSquares(numbers, squares) {\n    assert squares == numbers.collect { it * it }\n}\n"
  },
  {
    "path": "listings/chap18/Listing_18_03_ConcurrentSquaresTransitive.groovy",
    "content": "import static groovyx.gpars.GParsPool.withPool\n\nwithPool {\n    def numbers = [1, 2, 3,  4,  5,  6].makeConcurrent()\n    def squares = [1, 4, 9]\n    assert squares == numbers.collect{ it * it }.grep{ it < 10 }\n}"
  },
  {
    "path": "listings/chap18/Listing_18_04_MapFilterReduce.groovy",
    "content": "import static groovyx.gpars.GParsPool.withPool\n\nwithPool {\n    assert 55 == [0, 1, 2, 3, 4].parallel\n        .map    { it + 1  }\n        .map    { it ** 2 }\n        .reduce { a, b -> a + b }\n}"
  },
  {
    "path": "listings/chap18/Listing_18_05_SquaresMapReduce.groovy",
    "content": "import static groovyx.gpars.GParsPool.withPool\n\nwithPool {\n    def numbers = [1, 2, 3,  4,  5,  6]\n    assert [1, 4, 9] == numbers.parallel\n        .map    { it * it }\n        .filter { it < 10 }\n        .collection\n}"
  },
  {
    "path": "listings/chap18/Listing_18_06_Dataflow.groovy",
    "content": "import groovyx.gpars.dataflow.Dataflows\nimport static groovyx.gpars.dataflow.Dataflow.task\n\nfinal flow = new Dataflows()\ntask { flow.result = flow.x + flow.y }      //#1\ntask { flow.x = 10 }                        //|#2\ntask { flow.y = 5 }                         //|#2\nassert 15 == flow.result                    //#3\n//#1 Assign derived value\n//#2 Assign value\n//#3 Read value\n"
  },
  {
    "path": "listings/chap18/Listing_18_07_DataflowStreams.groovy",
    "content": "import static groovyx.gpars.dataflow.Dataflow.*\nimport groovyx.gpars.dataflow.DataflowQueue\n\ndef chances = new DataflowQueue()\ndef amounts = new DataflowQueue()\ndef payouts = new DataflowQueue()\n\noperator( inputs: [chances, amounts],\n          outputs:[payouts],\n        { chance, amount -> payouts << chance * amount }\n)\n\ntask { [0.1, 0.2, 0.3].each { chances << it } }\ntask { [300, 200, 100].each { amounts << it } }\n\n[30, 40, 30].each { assert it == payouts.val }"
  },
  {
    "path": "listings/chap18/Listing_18_08_Actors.groovy",
    "content": "import static groovyx.gpars.actor.Actors.*\n\ndef decrypt = reactor { code -> code.reverse() }   //#1\ndef audit   = reactor { println it }               //#2\n\ndef main    = actor   {                            //#3\n    decrypt 'terces pot'                           //#4\n    react { plainText ->                           //#5\n        audit plainText                            //#6\n    }\n}\nmain.join()\naudit.stop()\naudit.join()\n//#1 reactor factory method\n//#2 reactor factory method\n//#3 actor factory method\n//#4 send message\n//#5 wait for reply\n//#6 send message\n"
  },
  {
    "path": "listings/chap18/Listing_18_09_ActorsLifecycle.groovy",
    "content": "import static groovyx.gpars.actor.Actors.*\n\ndef stopper = reactor { stop() }\nstopper.metaClass.afterStop = { inbox -> println inbox }\nstopper.send()"
  },
  {
    "path": "listings/chap18/Listing_18_10_ActorsMessageAware.groovy",
    "content": "import static groovyx.gpars.actor.Actors.*\n\ndef manual = reactor { message ->\n    switch (message) {                          //#1\n        case Number: reply 'number'; break\n        case String: reply 'string'; break\n    }\n}\n\ndef auto = messageHandler {\n    when { String message -> reply 'string' }   //#2\n    when { Number message -> reply 'number' }\n}\n//#1 Self-made dispatch\n//#2 Groovy method dispatch\n"
  },
  {
    "path": "listings/chap18/Listing_18_11_Agent.groovy",
    "content": "import groovyx.gpars.agent.Agent\n\ndef guard = new Agent<String>()\n\nguard { updateValue 'GPars' }\nguard { updateValue(it + ' is groovy!') }\n\nassert \"GPars is groovy!\" == guard.val"
  },
  {
    "path": "listings/chap18/Listing_18_12.txt",
    "content": "see: YahooService.groovy"
  },
  {
    "path": "listings/chap18/Listing_18_13_YahooForkJoin.groovy",
    "content": "import static groovyx.gpars.GParsPool.withPool\nimport static YahooService.getYearEndClosing\n\ndef tickers = ['AAPL', 'GOOG', 'IBM', 'ORCL', 'MSFT']\n\nwithPool(tickers.size()) {\n  def top = tickers.makeConcurrent()\n      .collect { [ticker: it, price: getYearEndClosing(it, 2014)] }\n      .max { it.price }\n  assert top == [ticker: 'GOOG', price: 526.4024f]\n}"
  },
  {
    "path": "listings/chap18/Listing_18_14_YahooMapReduce.groovy",
    "content": "import static groovyx.gpars.GParsPool.withPool\nimport static YahooService.getYearEndClosing\n\ndef ticker = ['AAPL', 'GOOG', 'IBM', 'ORCL', 'MSFT']\n\nwithPool(ticker.size()) {\n  def top = ticker.parallel\n      .map { [ticker: it, price: getYearEndClosing(it, 2014)] }\n      .max { it.price }\n  assert top == [ticker: 'GOOG', price: 526.4024f]\n}"
  },
  {
    "path": "listings/chap18/Listing_18_15_YahooDataflow.groovy",
    "content": "import groovyx.gpars.dataflow.Dataflows\nimport static YahooService.getYearEndClosing\nimport static groovyx.gpars.dataflow.Dataflow.task\n\ndef tickers = ['AAPL', 'GOOG', 'IBM', 'ORCL', 'MSFT']\n\ndef price = new Dataflows()\ntickers.each { ticker ->\n  task { price[ticker] = getYearEndClosing(ticker, 2014) }     //#A\n}\ndef top = tickers.max { price[it] }                            //#B\nassert top == 'GOOG' && price[top] == 526.4024f\n//#A Set when available\n//#B Read sequentially\n"
  },
  {
    "path": "listings/chap18/YahooService.groovy",
    "content": "class YahooService {\n  static getYearEndClosingUnsafe(String ticker, int year) {\n    def url = \"http://real-chart.finance.yahoo.com/table.csv?\" +\n        \"s=$ticker&a=11&b=1&c=$year&d=11&e=31&f=$year&g=d&ignore=.csv\"\n    def data = url.toURL().text\n    return data.split(\"\\n\")[1].split(\",\")[4].toFloat()\n  }\n\n  static getYearEndClosing(String ticker, int year) {\n    try {\n      getYearEndClosingUnsafe(ticker, year)\n    } catch (all) {\n      println \"Could not get $ticker, returning -1. $all\"\n      return -1\n    }\n  }\n}\n"
  },
  {
    "path": "listings/chap18/snippet1801_startThread.groovy",
    "content": "def thread = Thread.start { println \"I'm in a new thread\" }\nthread.join()"
  },
  {
    "path": "listings/chap18/snippet1803_java_parallel_streams_jdk8_only.groovy",
    "content": "// Groovy with Java 8\ndef numbers = [1, 2, 3,  4,  5,  6]\nassert [1, 4, 9] == numbers.parallelStream()\n    .map    { it * it }\n    .filter { it < 10 }\n    .collect()\n"
  },
  {
    "path": "listings/chap18/snippet1804_deadlock.groovy",
    "content": "import groovyx.gpars.dataflow.Dataflows\nimport static groovyx.gpars.dataflow.Dataflow.task\n\nfinal flow = new Dataflows()\ntask { flow.x = flow.y }\t\t\t\ntask { flow.y = flow.x }"
  },
  {
    "path": "listings/chap18/snippet1804_nondeterministic.groovy",
    "content": "import groovyx.gpars.dataflow.Dataflows\nimport static groovyx.gpars.dataflow.Dataflow.task\n\nfinal flow = new Dataflows()\ntask { flow.list = [0] }\ntask { flow.list[0] = 1 }\nprintln flow.list"
  },
  {
    "path": "listings/chap19/FetchOptions.groovy",
    "content": "final class FetchOptions {                           //#2\n  private int limit, offset, chunkSize, prefetchSize\n\n  private FetchOptions() {}                          //#3\n\n  FetchOptions limit(int lim) {\n    this.limit = lim\n    return this                                      //#1\n  }\n\n  FetchOptions offset(int offs) {\n    this.offset = offs\n    return this\n  }\n\n  FetchOptions chunkSize(int cs) {\n    this.chunkSize = cs\n    return this\n  }\n\n  FetchOptions prefetchSize(int ps) {\n    this.prefetchSize = ps\n    return this\n  }\n\n  static final class Builder {                       //#5\n    private Builder() {}                             //#6\n    static FetchOptions withDefaults() {             //#4\n      new FetchOptions()                             //#4\n    }\n\n    static FetchOptions withLimit(int lim) {         //#7\n      new FetchOptions().limit(lim)\n    }\n\n    static FetchOptions withOffset(int offs) {\n      new FetchOptions().offset(offs)\n    }\n\n    static FetchOptions withChunkSize(int cs) {\n      new FetchOptions().chunkSize(cs)\n    }\n\n    static FetchOptions withPrefetchSize(int ps) {\n      new FetchOptions().prefetchSize(ps)\n    }\n  }\n}\n//#1 Enable chaining\n//#2 Non-extensible class\n//#3 Private constructor\n//#4 Default factory method\n//#5 Non-extensible class\n//#6 Private constructor\n//#7 One of several specialized factory methods\n"
  },
  {
    "path": "listings/chap19/FetchOptionsBuilder.groovy",
    "content": "class FetchOptionsBuilder {\n    static FetchOptions fetchOptions(Closure c) {\n        def opts = FetchOptions.Builder.withDefaults()\n        opts.with c\n        return opts\n    }\n}\n"
  },
  {
    "path": "listings/chap19/Listing_19_06_Binding.groovy",
    "content": "def binding = new Binding(distance: 11400, time: 5 * 60)  //#1\n\ndef shell = new GroovyShell(binding)        //#2\nshell.evaluate '''\n    speed = distance / time                 //#3\n'''\n\nassert binding.distance == 11400            //#4\nassert binding.time == 5 * 60               //#4\nassert binding.speed == 38                  //#5\n//#1 Create and populate binding\n//#2 Pass binding to GroovyShell\n//#3 Calculation only involving binding variables\n//#4 Input variables unchanged\n//#5 Result also in binding\n"
  },
  {
    "path": "listings/chap19/Listing_19_29_OrderDSL.groovy",
    "content": "def of = \"silent word\"                    //#1\n\ndef buy(n) {\n  [shares: { of ->                        //#2\n    [:].withDefault { ticker ->           //#3\n      println \"buy $n shares of $ticker\"\n    }\n  }]\n}\n\nbuy 200 shares of GOOG\n//#1 Define silent word\n//#2 Unused parameter\n//#3 Map with Closure defining behavior for unknown keys\n"
  },
  {
    "path": "listings/chap19/Listing_19_30_WhenIfControlStructure.groovy",
    "content": "def when(boolean condition, Closure block) {\n  if (condition) block()\n}\n\ndef a = 1\ndef b = 2\n\nwhen(a < b, { println \"a < b\" })        //#1\n\nwhen (a < b) { println \"a < b\" }\n//#1 Closure is the last parameter\n"
  },
  {
    "path": "listings/chap19/Listing_19_31_Until_failing_.groovy",
    "content": "def until(boolean condition, Closure closure) {\n  while (!condition) closure()\n}\n\ndef counter = 0\n\nuntil(counter == 10) {            //#1\n  counter++\n}\n//#1 Eagerly calculated expression\n"
  },
  {
    "path": "listings/chap19/Listing_19_32_UntilControlStructure.groovy",
    "content": "def until(Closure condition, Closure closure) {\n  while (!condition()) closure()      //#1\n}\n\ndef counter = 0\n\nuntil({ counter == 10 }) {             //#2\n  counter++\n}\n\nassert counter == 10\n//#1 Evaluating closure for each iteration\n//#2 Passing a closure as first parameter\n"
  },
  {
    "path": "listings/chap19/Listing_19_39_GivenWhenThen.groovy",
    "content": "def given(Closure g) {\n  def valueHolder = [:]\n  g.delegate = valueHolder\n  g.resolveStrategy = Closure.DELEGATE_FIRST\n  g()\n  [when: { Closure w ->\n    w.delegate = valueHolder\n    w.resolveStrategy = Closure.DELEGATE_FIRST\n    w()\n    [then: { Closure t ->\n      t.delegate = valueHolder\n      t.resolveStrategy = Closure.DELEGATE_FIRST\n      t()\n    }]\n  }]\n}\n\n\ngiven {\n  a = 1\n  b = 2\n} when {\n  result = a + b\n} then {\n  assert result == 3\n}\n"
  },
  {
    "path": "listings/chap19/Listing_19_43_FetchOptionsScript.groovy",
    "content": "import static FetchOptionsBuilder.fetchOptions\n\nfetchOptions {\n    limit 10 offset 60 \n    chunkSize 1000\n}\n"
  },
  {
    "path": "listings/chap19/Listing_19_44_RubyStyleNewify.groovy",
    "content": "import groovy.transform.ToString\n\n@ToString\nclass Car {\n  String make\n  String model\n}\n\n@Newify\ndef car = Car.new(make: 'Porsche', model: '911')\n\nassert car.toString() == 'Car(Porsche, 911)'\n"
  },
  {
    "path": "listings/chap19/Listing_19_45_PythonStyleNewify.groovy",
    "content": "import groovy.transform.Canonical\n\n@Canonical\nclass Country {\n  String name\n}\n\n@Canonical\nclass City {\n  String name\n  String zipCode\n  Country country\n}\n\n@Newify([City, Country])\ndef paris = City('Paris', '75000', Country('France'))\n\nassert paris.toString() == 'City(Paris, 75000, Country(France))'\n"
  },
  {
    "path": "listings/chap19/Listing_19_46_Terms.groovy",
    "content": "import groovy.transform.*\n\ninterface Term {}\n\n@Canonical\nclass Value implements Term {\n  def content\n}\n\n@Canonical\nclass Add implements Term {\n  def left, right\n}\n\n@Canonical\nclass Mult implements Term {\n  def left, right\n}\n\ndef term =\n    new Mult(new Value('a'), new Add(new Value('b'), new Value('c')))\n\n@Newify([Value, Mult, Add])\ndef term2 = Mult(Value('a'), Add(Value('b'), Value('c')))\n\nimport org.codehaus.groovy.control.CompilerConfiguration\nimport org.codehaus.groovy.control.customizers.ASTTransformationCustomizer\n\ndef config = new CompilerConfiguration()\nconfig.addCompilationCustomizers(\n    new ASTTransformationCustomizer(                    //#1\n        value: [Value, Mult, Add], Newify)              //#1\n)\ndef shell = new GroovyShell(\n    this.class.classLoader, new Binding(), config)      //#2\n\ndef term3 = shell.evaluate '''\n    Mult(                                               //#3\n        Value('a'),                                     //#3\n        Add(                                            //#3\n            Value('b'),                                 //#3\n            Value('c')                                  //#3\n        )                                               //#3\n    )                                                   //#3\n'''\n\nassert term3.toString() == 'Mult(Value(a), Add(Value(b), Value(c)))'\n//#1 Pass annotation and parameters to customizer\n//#2 Pass config to GroovyShell\n//#3 Implicit Newify\n"
  },
  {
    "path": "listings/chap19/Listing_19_47_NewifyInjected.txt",
    "content": "see second half of: Listing_19_46_Terms.groovy\n"
  },
  {
    "path": "listings/chap19/Listing_19_48_No_IO.groovy",
    "content": "import org.codehaus.groovy.control.*\nimport org.codehaus.groovy.control.customizers.*\n\ndef secure = new SecureASTCustomizer()\nsecure.starImportsBlacklist = ['java.io.*']          //#1\nsecure.indirectImportCheckEnabled = true             //#2\n\ndef config = new CompilerConfiguration()\nconfig.addCompilationCustomizers(secure)\n\ndef shell = new GroovyShell(config)\n\ngroovy.test.GroovyAssert.shouldFail {\n  shell.evaluate '''                                 //#3\n    new File('.')                                    //#3\n  '''                                                //#3\n}\n//#1 Disallow java.io imports\n//#2 Disallow explicit java.io class references\n//#3 Evaluate violating script\n"
  },
  {
    "path": "listings/chap19/Listing_19_49_ArithmeticShell.groovy",
    "content": "import org.codehaus.groovy.ast.expr.*\nimport org.codehaus.groovy.ast.stmt.*\nimport org.codehaus.groovy.control.CompilerConfiguration\nimport org.codehaus.groovy.control.customizers.ImportCustomizer\nimport org.codehaus.groovy.control.customizers.SecureASTCustomizer\n\nimport static org.codehaus.groovy.syntax.Types.*\n\ndef imports = new ImportCustomizer().addStaticStars('java.lang.Math')\ndef secure = new SecureASTCustomizer()\n\nsecure.with {\n  closuresAllowed = false                                           //#1\n  methodDefinitionAllowed = false                                   //#2\n\n  importsWhitelist = []                                             //#3\n  staticImportsWhitelist = []                                       //#3\n  staticStarImportsWhitelist = ['java.lang.Math']                   //#3\n\n  tokensWhitelist = [                                               //#4\n    PLUS, MINUS, MULTIPLY, DIVIDE, MOD, POWER, PLUS_PLUS,\n    MINUS_MINUS, COMPARE_EQUAL, COMPARE_NOT_EQUAL,\n    COMPARE_LESS_THAN, COMPARE_LESS_THAN_EQUAL,\n    COMPARE_GREATER_THAN, COMPARE_GREATER_THAN_EQUAL,\n  ]\n\n  constantTypesClassesWhiteList = [                                 //#5\n    Integer, Float, Long, Double, BigDecimal,\n    Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE\n  ]\n\n  receiversClassesWhiteList = [                                     //#6\n    Math, Integer, Float, Double, Long, BigDecimal\n  ]\n\n  statementsWhitelist = [                                           //#7\n    BlockStatement, ExpressionStatement\n  ]\n\n  expressionsWhitelist = [                                          //#8\n    BinaryExpression,       ConstantExpression,\n    MethodCallExpression,   StaticMethodCallExpression,\n    ArgumentListExpression, PropertyExpression,\n    UnaryMinusExpression,   UnaryPlusExpression,\n    PrefixExpression,       PostfixExpression,\n    TernaryExpression,      ElvisOperatorExpression,\n    BooleanExpression,      ClassExpression\n  ]\n}\ndef config = new CompilerConfiguration()\nconfig.addCompilationCustomizers(imports, secure)\ndef shell = new GroovyShell(config)\ndef result = shell.evaluate('1+cos(PI/2)')                          //#9\nassert result == 1\n//#1 Disable closures\n//#2 Disable methods\n//#3 Disable imports and static imports except lava.lang.Math\n//#4 Allow mathematical tokens\n//#5 Allow number types\n//#6 Allow number receivers\n//#7 Allow only blocks and statements\n//#8 Allow only math-related expressions\n//#9 Run the shell\n"
  },
  {
    "path": "listings/chap19/Listing_19_50_TimedInterrupt.groovy",
    "content": "import groovy.transform.*\nimport org.codehaus.groovy.control.*\nimport org.codehaus.groovy.control.customizers.*\nimport java.util.concurrent.TimeoutException\nimport static groovy.test.GroovyAssert.shouldFail\n\ndef config = new CompilerConfiguration()                         //#2\nconfig.addCompilationCustomizers(                                //#2\n    new ASTTransformationCustomizer(value: 2, TimedInterrupt)    //#2\n)\ndef shell = new GroovyShell(config)\ndef te = shouldFail(TimeoutException) {\n    shell.evaluate '''\n       for (i in 1..1000) {                                  //#1\n         sleep 1000                                          //#1\n       }\n    '''\n}\nprintln te.message\n//#1 Create lengthy loop\n//#2 Add 2 second timeout to our script\n"
  },
  {
    "path": "listings/chap19/Listing_19_51_SystemExitGuard.groovy",
    "content": "import org.codehaus.groovy.ast.*\nimport org.codehaus.groovy.ast.expr.*\nimport org.codehaus.groovy.control.*\nimport org.codehaus.groovy.control.customizers.*\nimport org.codehaus.groovy.classgen.*\nimport org.codehaus.groovy.syntax.*\nimport static groovy.test.GroovyAssert.shouldFail\nimport static org.codehaus.groovy.control.CompilePhase.*\n\ndef config = new CompilerConfiguration()\ndef filter = new CompilationCustomizer(CANONICALIZATION) {          //#1\n  void call(SourceUnit src, GeneratorContext ctxt, ClassNode cn) {  //#2\n    new ClassCodeVisitorSupport() {                                 //#3\n      void visitMethodCallExpression(MethodCallExpression call) {   //#4\n        if (call.objectExpression.text == 'java.lang.System' &&     //#5\n        call.method.text == 'exit') {                               //#5\n          src.addError(new SyntaxException(                         //#6\n              'System.exit() forbidden',                            //#6\n              call.lineNumber, call.columnNumber))                  //#6\n        }\n        super.visitMethodCallExpression(call)\n      }\n      SourceUnit getSourceUnit() { src }\n    }.visitClass(cn)\n  }\n}\nconfig.addCompilationCustomizers(filter)\n\ndef shell = new GroovyShell(config)\ndef ce = shouldFail(CompilationFailedException) {\n  shell.parse '''\n    System.exit(0)\n  '''\n}\nprintln ce.message\n//#1 Extend CompilationCustomizer\n//#2 Override call method\n//#3 Define visitor\n//#4 Override method call visits\n//#5 Detect System.exit\n//#6 Flag error\n"
  },
  {
    "path": "listings/chap19/Listing_19_53_QueryCustomizer.groovy",
    "content": "import org.codehaus.groovy.ast.ClassCodeVisitorSupport\nimport org.codehaus.groovy.ast.ClassNode\nimport org.codehaus.groovy.ast.expr.MethodCallExpression\nimport org.codehaus.groovy.ast.expr.StaticMethodCallExpression\nimport org.codehaus.groovy.classgen.GeneratorContext\nimport org.codehaus.groovy.control.SourceUnit\nimport org.codehaus.groovy.control.customizers.CompilationCustomizer\nimport org.codehaus.groovy.syntax.SyntaxException\nimport static org.codehaus.groovy.control.CompilePhase.*\n\nnew CompilationCustomizer(SEMANTIC_ANALYSIS) {\n  void call(SourceUnit src, GeneratorContext ctxt, ClassNode cn) {\n    new ClassCodeVisitorSupport() {\n      boolean inQueryClosure = false\n\n      void visitStaticMethodCallExpression(                           //#1\n          StaticMethodCallExpression call) {                          //#1\n        if (call.method == 'query' && call.ownerType.name == 'Query') //#1\n          inQueryClosure = true\n        super.visitStaticMethodCallExpression(call)\n        if (inQueryClosure) \n          inQueryClosure = false\n      }\n\n      void visitMethodCallExpression(MethodCallExpression call) {\n        def methName = call.method.text \n        if (\n          inQueryClosure &&                                         //#2\n          call.objectExpression.text == 'this' &&                   //#2\n          !(methName in ['select', 'from', 'where'])) {             //#2\n            src.addError(new SyntaxException(                       //#3\n              \"No query verb ${methName}, only select/from/where\",  //#3\n              call.lineNumber, call.columnNumber))                  //#3\n        }\n        super.visitMethodCallExpression(call)\n      }\n\n      SourceUnit getSourceUnit() { src }\n    }.visitClass(cn)\n  }\n}\n\nQuery.query {\n    select all from table where true\n}\n//#1 Track when inside Query.query\n//#2 Check  method calls are to known methods\n//#3 Add error if unknown methods found\n"
  },
  {
    "path": "listings/chap19/Listings.txt",
    "content": "Listing number and folder name (or file name if not standard form of Listing_19_XX_YY.groovy)\n19_01: v01/\n19_02: v02/model/Direction.groovy\n19_03: v02/model/Robot.groovy\n19_04: v02/\n19_05: v02/\n19_06: /\n19_07: v02/\n19_08: v02/\n19_09: v02/\n19_10: v02/\n19_11: v02/integration/RobotBaseScript.groovy\n19_12: v02/\n19_13: v02/\n19_14: v02/\n19_15: v03/integration/RobotBaseScript.groovy\n19_16: v02/\n19_17: v02/integration/CaseRobotBaseScript.groovy\n19_18: v02/integration/CustomBinding.groovy\n19_19: v02/\n19_20: v03/model/Unit.groovy\n19_21: v03/model/Distance.groovy\n19_22: v03/integration/DistanceCategory.groovy\n19_23: v03/integration/DistanceCategory.groovy (yes, it is the same)\n19_24: v03/model/Speed.groovy\n19_25: v03/model/Duration.groovy\n19_26: v03/model/Distance.groovy (yes, again)\n19_27: v03/Listing_19_27_SimpleCommandChain.groovy\n19_28: v03/Listing_19_27_SimpleCommandChain.groovy (again)\n19_29: /\n19_30: /\n19_31: /\n19_32: /\n19_33: xform/CustomControlStructure.groovy\n19_34: xform/WhenUntilTransform_Structure.groovy\n19_35: xform/BusinessLogicScript.groovy\n19_36: xform/\n19_37: xform/WhenUtilTransform.groovy (just visit method)\n19_38: xform/WhenUtilTransform.groovy (same file: full)\n19_39: /\n19_40: v03/\n19_41: FetchOptions.groovy\n19_42: FetchOptionsBuilder.groovy\n19_43: /\n19_44: /\n19_45: /\n19_46: Listing_19_46_Terms.groovy (part 1)\n19_47: Listing_19_46_Terms.groovy (part 2)\n19_48: /\n19_49: /\n19_50: /\n19_51: /\n19_52: Query.groovy\n19_53: /\n\n\n"
  },
  {
    "path": "listings/chap19/Query.groovy",
    "content": "class Query {\n  static query(Closure c) {                              //#1\n    def q = c.clone()                                    //#2\n    q.resolveStrategy = Closure.DELEGATE_FIRST           //#2\n    q.delegate = new Query()                             //#2\n    q()                                                  //#2\n  }\n\n  def getProperty(String name) { name }                  //#3\n\n  Query select(column)   { this }                        //#4\n  Query from(table)      { this }                        //#4\n  Query where(condition) { this }                        //#4\n}\n//#1 DSL entry point\n//#2 Define delegate and resolution strategy\n//#3 Trivial implementation of property resolution\n//#4 Enable method chaining\n"
  },
  {
    "path": "listings/chap19/extra_FetchOptions_traditional.groovy",
    "content": "\ndef options = FetchOptions.Builder.withLimit(10).offset(60).chunkSize(1000)\nprintln options\n"
  },
  {
    "path": "listings/chap19/v01/Listing_19_01_SelfContainedScript.groovy",
    "content": "package v01\n\nimport static Direction.*                //#2\n\nenum Direction {                         //#1\n  left, right, forward, backward         //#1\n}                                        //#1\n\nclass Robot {                            //#3\n  void move(Direction dir) {             //#4\n    println \"robot moved $dir\"           //#4\n  }                                      //#4\n}\n\ndef robot = new Robot()                  //#5\n\nrobot.move left                          //#6\n//#1 The enum definition\n//#2 Make constants available in script\n//#3 Define class\n//#4 Method definition\n//#5 Create instance\n//#6 Instruct robot to move\n"
  },
  {
    "path": "listings/chap19/v02/Listing_19_04_MainSimple.groovy",
    "content": "package v02\n\nimport v02.model.Robot                            //#A\nimport static v02.model.Direction.*               //#B\n\ndef robot = new Robot()\n\nrobot.move left\n//#A Import Robot class from model package\n//#B Use static import for directions\n"
  },
  {
    "path": "listings/chap19/v02/Listing_19_05_MainGroovyShell.groovy",
    "content": "package v02\n\ndef shell = new GroovyShell()                                    //#1\nshell.evaluate '''                                               //#2\nimport v02.model.Robot                                           //#2\nimport static v02.model.Direction.*                              //#2\n                                                                 //#2\ndef robot = new Robot()                                          //#2\n                                                                 //#2\nrobot.move left                                                  //#2\n'''                                                              //#2\n//#1 Instantiates the shell\n//#2 Shell evaluates inline script\n"
  },
  {
    "path": "listings/chap19/v02/Listing_19_07_MainBinding.groovy",
    "content": "package v02\n\nimport v02.model.Robot\n\ndef binding = new Binding(robot: new Robot())                  //#1\n\ndef shell = new GroovyShell(this.class.classLoader, binding)   //#2\nshell.evaluate '''\n    import static v02.model.Direction.*\n\n    robot.move left\n'''\n//#1 Create binding using named params or map\n//#2 Binding passed to GroovyShell constructor\n"
  },
  {
    "path": "listings/chap19/v02/Listing_19_08_MainDirectionConstants.groovy",
    "content": "package v02\n\nimport v02.model.*\n\ndef binding = new Binding(\n    robot:     new Robot(),\n    left:      Direction.left,            //#1\n    right:     Direction.right,           //#1\n    forward:   Direction.forward,         //#1\n    backward:  Direction.backward         //#1\n)\n\ndef shell = new GroovyShell(this.class.classLoader, binding)\nshell.evaluate '''\n    robot.move left                       //#2\n'''\n//#1 Inject directions\n//#2 Import free script\n"
  },
  {
    "path": "listings/chap19/v02/Listing_19_09_MainDirectionsSpread.groovy",
    "content": "package v02\n\nimport v02.model.*\n\ndef binding = new Binding(\n    robot: new Robot(),\n    *: Direction.values().collectEntries { [(it.name()): it] }   //#1\n)\n\ndef shell = new GroovyShell(this.class.classLoader, binding)\nshell.evaluate '''\n    robot.move left\n'''\n//#1 Inject directions using spread-map operator\n"
  },
  {
    "path": "listings/chap19/v02/Listing_19_10_MainImplicitMethod.groovy",
    "content": "package v02\n\nimport org.codehaus.groovy.control.CompilerConfiguration\nimport org.codehaus.groovy.control.customizers.*\nimport v02.model.Robot\n\ndef binding = new Binding(robot: new Robot())\n\ndef importCustomizer = new ImportCustomizer()\nimportCustomizer.addStaticStars 'v02.model.Direction'\n\ndef config = new CompilerConfiguration()\nconfig.addCompilationCustomizers importCustomizer\n\ndef shell = new GroovyShell(this.class.classLoader, binding, config)\nshell.evaluate '''\n    move left\n''' + '''\n    def move(dir) {\n        robot.move dir\n    }\n'''"
  },
  {
    "path": "listings/chap19/v02/Listing_19_12_MainBaseScript.groovy",
    "content": "package v02\n\nimport v02.model.*\n\ndef binding = new Binding(\n    robot: new Robot(),\n    *: Direction.values().collectEntries { [(it.name()): it] }\n)\n\ndef shell = new GroovyShell(this.class.classLoader, binding)\nshell.evaluate '''\n@BaseScript(v02.integration.RobotBaseScript)\nimport groovy.transform.BaseScript\n\nmove left\n'''\n"
  },
  {
    "path": "listings/chap19/v02/Listing_19_13_MainImportCustomizer.groovy",
    "content": "package v02\n\nimport org.codehaus.groovy.control.CompilerConfiguration\nimport org.codehaus.groovy.control.customizers.*\nimport v02.model.Robot\n\ndef binding = new Binding(robot: new Robot())                       //#1\n\ndef importCustomizer = new ImportCustomizer()                       //#2\nimportCustomizer.addStaticStars 'v02.model.Direction'               //#3\n\ndef config = new CompilerConfiguration()\nconfig.addCompilationCustomizers importCustomizer                   //#4\n\ndef shell = new GroovyShell(this.class.classLoader, binding, config)  //#5\nshell.evaluate '''\n    robot.move left\n'''\n//#1 Inject only variables into binding\n//#2 Create import customizer\n//#3 Direction.* enum values statically imported with star import\n//#4 Import customizer added to compiler configuration\n//#5 Compiler configuration passed to GroovyShell\n"
  },
  {
    "path": "listings/chap19/v02/Listing_19_14_MainCustomBaseScriptClass.groovy",
    "content": "package v02\n\nimport org.codehaus.groovy.control.CompilerConfiguration\nimport org.codehaus.groovy.control.customizers.*\nimport v02.integration.RobotBaseScript\nimport v02.model.*\n\ndef binding = new Binding(robot: new Robot())\n\ndef importCustomizer = new ImportCustomizer()\nimportCustomizer.addStaticStars Direction.name\n\ndef config = new CompilerConfiguration()\nconfig.addCompilationCustomizers importCustomizer\nconfig.scriptBaseClass = RobotBaseScript.name                   //#A\n\ndef shell = new GroovyShell(this.class.classLoader, binding, config)\nshell.evaluate '''\n    move left\n'''\n//#A Specify script base class"
  },
  {
    "path": "listings/chap19/v02/Listing_19_16_MainMethodClosure.groovy",
    "content": "package v02\n\nimport v02.model.*\n\ndef robot = new Robot()\ndef binding = new Binding(\n    robot: robot,\n    move: robot.&move,                                              //#1\n    *: Direction.values().collectEntries { [(it.name()): it] }\n)\n\ndef shell = new GroovyShell(this.class.classLoader, binding)\nshell.evaluate '''\n    move left\n'''\n//#1 Method closure reference to robot’s move() method\n"
  },
  {
    "path": "listings/chap19/v02/Listing_19_19_MainLowerCase.groovy",
    "content": "package v02\n\nimport org.codehaus.groovy.control.*\nimport v02.integration.*\nimport v02.model.*\n\ndef binding = new CustomBinding(robot: new Robot())\n\ndef config = new CompilerConfiguration()\nconfig.scriptBaseClass = CaseRobotBaseScript.name                 //#A\n\ndef shell = new GroovyShell(this.class.classLoader, binding, config)\nshell.evaluate '''\n    mOVe lEfT\n'''\n//#A Specify script base class\n"
  },
  {
    "path": "listings/chap19/v02/integration/CaseRobotBaseScript.groovy",
    "content": "package v02.integration\n\nabstract class CaseRobotBaseScript extends RobotBaseScript {\n  def invokeMethod(String name, args) {                           //#1\n    getBinding().robot.\"${name.toLowerCase()}\"(*args)             //#2\n  }\n}\n//#1 Intercept method invocation\n//#2 Mixed-case script calls become lowercase robot calls\n"
  },
  {
    "path": "listings/chap19/v02/integration/CustomBinding.groovy",
    "content": "package v02.integration\n\nimport v02.model.Direction\n\nclass CustomBinding extends Binding {\n  private Map variables\n\n  CustomBinding(Map vars) {\n    this.variables = [\n        *: vars,                                                    //#1\n        *: Direction.values().collectEntries { [(it.name()): it] }  //#1\n    ]\n  }\n\n  def getVariable(String name) {\n    variables[name.toLowerCase()]                                   //#2\n  }\n\n}\n//#1 Merge constructor variables and Direction constants\n//#2 Variable lookup via lowercase key\n"
  },
  {
    "path": "listings/chap19/v02/integration/RobotBaseScript.groovy",
    "content": "package v02.integration\n\nimport v02.model.Direction\n\nabstract class RobotBaseScript extends Script {\n  void move(Direction dir) {\n    this.binding.robot.move dir\n  }\n}\n"
  },
  {
    "path": "listings/chap19/v02/model/Direction.groovy",
    "content": "package v02.model\n\nenum Direction {\n  left, right, forward, backward\n}\n"
  },
  {
    "path": "listings/chap19/v02/model/Robot.groovy",
    "content": "package v02.model\n\nclass Robot {\n  void move(Direction dir) {\n    println \"robot moved $dir\"\n  }\n}\n"
  },
  {
    "path": "listings/chap19/v02/snippet1901_MainFileRunner.groovy",
    "content": "package v02\n\nimport v02.model.Robot\n\ndef shell = new GroovyShell(this.class.classLoader)\n\n// assumes script is run from parent directory\nshell.evaluate 'v02/CommandScript.groovy' as File\n\n// assumes script is on the classpath\ndef script = Robot.getResource(\"/v02/CommandScript.groovy\")\nshell.evaluate new File(script.toURI())\n"
  },
  {
    "path": "listings/chap19/v03/Listing_19_27_SimpleCommandChain.groovy",
    "content": "package v03\n\nimport v03.model.*\nimport v03.integration.*\nimport static v03.model.Direction.right\n\n// listing 19.27\ndef move(Direction dir) {\n    [by: { Distance dist ->\n        [at: { Speed speed ->\n            println \"robot moved $dir by $dist at $speed\"\n        }]\n    }]\n}\n// end\n\nuse(DistanceCategory) {\n    def h = Duration.hour\n    // listing 19.28\n    def map1 = move(right)\n    def byClosure = map1['by']\n    def map2 = byClosure(3.meters)\n    def atClosure = map2['at']\n    atClosure(5.km / h)\n    // end\n    move right by 3.meters at 5.km/h\n}"
  },
  {
    "path": "listings/chap19/v03/Listing_19_40_Robot_With.groovy",
    "content": "package v03\n\nimport v03.model.Robot\nimport static v03.model.Direction.*\n\ndef robot = new Robot()\n\nrobot.with {       //#1\n  move left            //#2\n  move forward         //#2\n}\n//#1 Demarcate block where robot will be delegate\n//#2 Streamlined syntax available within block\n"
  },
  {
    "path": "listings/chap19/v03/integration/DistanceCategory.groovy",
    "content": "package v03.integration\n\nimport v03.model.*\n\nclass DistanceCategory {\n  static Distance getCentimeters(Number num) {\n    new Distance(num, Unit.centimeter)\n  }\n\n  static Distance getMeters(Number num) {\n    new Distance(num, Unit.meter)\n  }\n\n  static Distance getKilometers(Number num) {\n    new Distance(num, Unit.kilometer)\n  }\n\n  static Distance getCm(Number num) { getCentimeters(num) }\n\n  static Distance getM(Number num) { getMeters(num) }\n\n  static Distance getKm(Number num) { getKilometers(num) }\n}\n"
  },
  {
    "path": "listings/chap19/v03/integration/RobotBaseScript.groovy",
    "content": "package v03.integration\n\nimport v03.model.Robot\n\nabstract class RobotBaseScript extends Script {\n  // In some older version of Groovy there was a bug where @Lazy\n  // and @Delegate didn't work together. If you have troubles,\n  // comment out the existing line and replace with next line:\n  // @Delegate Robot robot = new Robot()\n  @Delegate @Lazy Robot robot = this.binding.robot\n}\n"
  },
  {
    "path": "listings/chap19/v03/integration/SuperBotBaseScript.groovy",
    "content": "package v03.integration\n\nimport v03.model.SuperBot\n\nabstract class SuperBotBaseScript extends Script {\n  // In some older version of Groovy there was a bug where @Lazy\n  // and @Delegate didn't work together. If you have troubles,\n  // comment out the existing line and replace with next line:\n  // @Delegate SuperBot robot = new SuperBot()\n  @Delegate @Lazy SuperBot robot = this.binding.robot\n}\n"
  },
  {
    "path": "listings/chap19/v03/model/Direction.groovy",
    "content": "package v03.model\n\nenum Direction {\n  left, right, forward, backward\n}\n"
  },
  {
    "path": "listings/chap19/v03/model/Distance.groovy",
    "content": "package v03.model\n\nimport groovy.transform.TupleConstructor\n\n@TupleConstructor\nclass Distance {\n  Number amount\n  Unit unit\n\n  Speed div(Duration dur) {\n    new Speed(amount, unit)\n  }\n\n  String toString() { \"$amount$unit\" }\n}\n"
  },
  {
    "path": "listings/chap19/v03/model/Duration.groovy",
    "content": "package v03.model\n\nenum Duration {\n  hour\n}\n"
  },
  {
    "path": "listings/chap19/v03/model/Robot.groovy",
    "content": "package v03.model\n\nclass Robot {\n  def move(Direction dir) {\n    println \"robot moved $dir\"\n  }\n\n  def move(Direction dir, Distance d) {\n    println \"robot moved $dir by $d\"\n  }\n\n  def move(Map m, Direction dir) {\n    println \"robot moved $dir by $m.by at ${m.at ?: '1 km/h'}\"\n  }\n}\n"
  },
  {
    "path": "listings/chap19/v03/model/Speed.groovy",
    "content": "package v03.model\n\nimport groovy.transform.TupleConstructor\n\n@TupleConstructor\nclass Speed {\n  Number amount\n  Unit unit\n\n  String toString() { \"$amount $unit/h\" }\n}\n"
  },
  {
    "path": "listings/chap19/v03/model/SuperBot.groovy",
    "content": "package v03.model\n\nclass SuperBot extends Robot {\n  def move(Direction dir) {\n    [by: { Distance dist ->\n      [at: { Speed s ->\n        println \"robot moved $dir by $dist at $s\"\n      }]\n    }]\n  }\n\n  def deploy(Direction dir) {\n    [arm: { -> println \"deploy $dir arm\" }()]\n  }\n}\n"
  },
  {
    "path": "listings/chap19/v03/model/Unit.groovy",
    "content": "package v03.model\n\nenum Unit {\n  centimeter('cm', 0.01),\n  meter     ( 'm',    1),\n  kilometer ('km', 1000)\n\n  String abbreviation\n  double multiplier\n\n  Unit(String abbr, double mult) {\n    this.abbreviation = abbr\n    this.multiplier = mult\n  }\n\n  String toString() { abbreviation }\n}\n"
  },
  {
    "path": "listings/chap19/xform/BusinessLogicScript.groovy",
    "content": "package xform\n\nabstract class BusinessLogicScript extends Script {\n    def when(boolean condition, Closure closure) {\n        if (condition) closure()\n    }\n}\n"
  },
  {
    "path": "listings/chap19/xform/CustomControlStructure.groovy",
    "content": "package xform\n\nimport java.lang.annotation.*\nimport org.codehaus.groovy.transform.*\n\n@Retention(RetentionPolicy.SOURCE)                                  //#1\n@Target(ElementType.TYPE)                                           //#2\n@GroovyASTTransformationClass(classes = [WhenUntilTransform])       //#3\n@interface CustomControlStructure {}\n//#1 Annotation thrown away before runtime\n//#2 Class annotation\n//#3 Reference to transform implementation class\n"
  },
  {
    "path": "listings/chap19/xform/Listing_19_36_WhenTransformation.groovy",
    "content": "package xform\n\nimport org.codehaus.groovy.control.CompilerConfiguration\nimport org.codehaus.groovy.control.customizers.ASTTransformationCustomizer\n\ndef binding = new Binding([customer: [name: 'John Doe', age: 32]])  //#1\n\ndef config = new CompilerConfiguration()                            //#2\nconfig.scriptBaseClass = BusinessLogicScript.class.name             //#3\nconfig.addCompilationCustomizers(                                   //#4\n    new ASTTransformationCustomizer(CustomControlStructure))        //#4\n\ndef shell = new GroovyShell(this.class.classLoader, binding, config)  //#5\ndef result = shell.evaluate '''                                     //#6\n    when (customer.age >= 21) {                                     //#6\n        \"Alcohol allowed for ${customer.name}\"                      //#6\n    }                                                               //#6\n'''                                                                 //#6\nassert result == \"Alcohol allowed for John Doe\"                     //#7\n//#1 Populate binding with customer\n//#2 Config instance\n//#3 Define base script\n//#4 Inject transform annotation\n//#5 Create configured shell\n//#6 Evaluate script\n//#7 Confirm result\n"
  },
  {
    "path": "listings/chap19/xform/WhenUntilTransform.groovy",
    "content": "package xform\n\nimport org.codehaus.groovy.ast.*\nimport org.codehaus.groovy.ast.expr.*\nimport org.codehaus.groovy.ast.stmt.*\nimport org.codehaus.groovy.control.*\nimport org.codehaus.groovy.transform.*\n\n@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)\nclass WhenUntilTransform implements ASTTransformation {\n    void visit(ASTNode[] nodes, SourceUnit unit) {\n        ClassNode annotatedClass = nodes[1]\n        new ClassCodeVisitorSupport() {\n            def currentMethod\n            def currentBlock\n            def currentStatement\n            void visitMethod(MethodNode method) {\n                currentMethod = method\n                super.visitMethod(method)\n            }\n            void visitBlockStatement(BlockStatement block) {\n                currentBlock = block\n                super.visitBlockStatement(block)\n            }\n            void visitExpressionStatement(ExpressionStatement statement) {\n                currentStatement = statement\n                super.visitExpressionStatement(statement)\n            }\n            void visitMethodCallExpression(MethodCallExpression mCall) {\n                if (\n                    mCall.objectExpression instanceof VariableExpression &&\n                    mCall.objectExpression.variable == 'this' &&\n                    mCall.method instanceof ConstantExpression &&\n                    mCall.method.value == 'when' &&\n                    mCall.arguments.expressions.size() == 1\n                ) {\n                    def idx = currentBlock.statements.findIndexOf {\n                        it == currentStatement\n                    }\n                    if (idx + 1 >= currentBlock.statements.size()) {\n                        addError(\n                            \"The when instruction has no body.\", mCall)\n                    } else {\n                        def whenCode = currentBlock.statements[idx + 1]\n                        def closureExp = new ClosureExpression(\n                            Parameter.EMPTY_ARRAY, whenCode)\n                        closureExp.variableScope = new VariableScope()\n                        closureExp.variableScope.parent =\n                            currentBlock.variableScope\n                        mCall.arguments.addExpression(closureExp)\n                        currentBlock.statements.remove(idx + 1)\n                    }\n                }\n                super.visitMethodCallExpression(mCall)\n            }\n            protected SourceUnit getSourceUnit() { unit }\n        }.visitClass(annotatedClass)\n    }\n}\n"
  },
  {
    "path": "listings/chap19/xform/extra_WhenTransformationWorksWithoutBraces.groovy",
    "content": "package xform\n\nimport org.codehaus.groovy.control.CompilerConfiguration\nimport org.codehaus.groovy.control.customizers.ASTTransformationCustomizer\n\ndef binding = new Binding([customer: [name: 'John Doe', age: 32]])  //#1\n\ndef config = new CompilerConfiguration()                            //#2\nconfig.scriptBaseClass = BusinessLogicScript.class.name             //#3\nconfig.addCompilationCustomizers(                                   //#4\n    new ASTTransformationCustomizer(CustomControlStructure))        //#4\n\ndef shell = new GroovyShell(this.class.classLoader, binding, config)  //#5\ndef result = shell.evaluate '''\n    when (customer.age >= 21)\n        \"Alcohol allowed for ${customer.name}\"\n\n'''                                                                 //#6\nassert result == \"Alcohol allowed for John Doe\"                     //#7\n"
  },
  {
    "path": "listings/chap19/xform/snippet1906_WhenUntilXform_Structure.groovy",
    "content": "package xform\n\n// checks that our skeleton contains no typos\nnew GroovyShell().parse '''\nimport org.codehaus.groovy.ast.*\nimport org.codehaus.groovy.control.*\nimport org.codehaus.groovy.transform.*\n\n@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)\nclass WhenUntilTransform implements ASTTransformation {\n    void visit(ASTNode[] nodes, SourceUnit unit) {\n        // we’ll fill in the gaps!\n    }\n}\n'''\n"
  },
  {
    "path": "listings/chap20/Listing_20_01_Grapes_for_twitter_urls.groovy",
    "content": "@Grab(group='org.ccil.cowan.tagsoup', module='tagsoup', version='1.2')\nimport org.ccil.cowan.tagsoup.Parser\n\ndef parser = new XmlParser(new Parser())\ndef html = parser.parse(\"http://manning.com/koenig2\")\n\ndef twitterUrls = html.body.'**'.a.@href.grep(~/.*twitter.*/)\nprintln twitterUrls.join(\"\\n\")\n\nassert 'http://www.twitter.com/mittie' in twitterUrls"
  },
  {
    "path": "listings/chap20/Listing_20_02_Scriptom_Windows_only.groovy",
    "content": "//@Grab('org.codehaus.groovy.modules.scriptom:scriptom:1.6.0')\n//@GrabExclude(\"org.codehaus.groovy:groovy\")\nimport org.codehaus.groovy.scriptom.ActiveXObject\n\ndef explorer = new ActiveXObject('InternetExplorer.Application')\nexplorer.Visible    = true\nexplorer.AddressBar = true\nexplorer.Navigate('http://www.groovy-lang.org/')\n"
  },
  {
    "path": "listings/chap20/Listing_20_03_ActivX_Windows_only.groovy",
    "content": "//@Grab('org.codehaus.groovy.modules.scriptom:scriptom:1.6.0')\n//@GrabExclude(\"org.codehaus.groovy:groovy\")\nimport org.codehaus.groovy.scriptom.ActiveXObject\n\ndef PARENT = 0\ndef OPTS   = 0\ndef sh     = new ActiveXObject('Shell.Application')\ndef folder = sh.BrowseForFolder(PARENT, 'Choose a folder', OPTS)\nprintln \"Chosen folder: ${folder.Items().Item().Path.value}\"\n"
  },
  {
    "path": "listings/chap20/Listing_20_10_SquaringMapValue.groovy",
    "content": "def squareMapValues = { map ->\n    if (map == null) { return null }\n    if (!map) { return [] }\n    return map.values().collect { it * it }\n}\nassert [1, 4, 9] == squareMapValues([a: 1, b: 2, c: 3])\n"
  },
  {
    "path": "listings/chap20/Listing_20_11_Synchronized.groovy",
    "content": "class Person {\n    List addresses\n\n    @groovy.transform.Synchronized\n    void setAddresses(List addresses) {\n        this.addresses.clear()\n        this.addresses.addAll(addresses)\n    }\n}\n\nassert new Person()"
  },
  {
    "path": "listings/chap20/Listing_20_12_DbC_invariants.groovy",
    "content": "@Grab('org.gcontracts:gcontracts-core:1.2.12')\nimport org.gcontracts.annotations.*\n\n@Invariant({ waterVolume >= 0; waterVolume <= maxVolume })\nclass Kettle {\n    int waterVolume = 0\n    int maxVolume = 1000\n\n    // listing 20.13:\n    @Requires({ amount > 0 })\n    @Ensures({ waterVolume == maxVolume || waterVolume > old.waterVolume })\n    void addWater(int amount) {\n        waterVolume = Math.min(maxVolume, amount + waterVolume)\n    }\n\n    // listing 20.14\n    @Requires({ desiredAmount > 0 })\n    @Ensures({\n        result >= 0;\n        result == 0 ? waterVolume == old.waterVolume : waterVolume < old.waterVolume\n    })\n    int pour(int desiredAmount) {\n        int amountPoured = (desiredAmount <= waterVolume\n                ? desiredAmount\n                : waterVolume)\n        waterVolume = waterVolume - amountPoured\n        amountPoured\n    }\n\n}\n\ndef kettle = new Kettle()\nkettle.addWater(600)\nkettle.addWater(600)\nassert kettle.waterVolume == kettle.maxVolume"
  },
  {
    "path": "test.groovy",
    "content": "import groovy.io.FileType\n\ndef failed = []\ndef excludes = [\n    '_failing_',                                  // any script that is meant to fail\n    'snippet1901_MainFileRunner.groovy',          // requires a src file on classpath\n    'Listing_10_46_RobotExtension.groovy',        // TC extension not standalone\n    'Listing_10_47_SQLExtension.groovy',          // TC extension not standalone\n    'Listing_12_16_GroovletExample.groovy',       // starts a servlet engine\n    'Listing_12_17_HelloWorldGroovlet.groovy',    // groovlet; not standalone script\n    'Listing_12_19_InspectGroovlet.groovy',       // groovlet; not standalone script\n    'Listing_12_20_HiLowGame.groovy',             // groovlet; not standalone script\n    'Listing_12_22_TemplateGroovlet.groovy',      // groovlet; not standalone script\n    'Listing_13_25_AthleteAppMain.groovy',        // meant to run from commandline\n    'Listing_13_27_MongoAthletes.groovy',         // requires mongodb to be installed\n    'Listing_15_10_XMLRPC_jira.groovy',           // requires codehaus JIRA credentials\n    'extra_NeoGremlinGraph.groovy',               // Grab seems a little fragile and only extra example\n]\n\ndef ver = System.getProperty('java.version')[0..2].toBigDecimal()\ndef os = System.getProperty(\"os.name\").toLowerCase()\n\nif (os.contains('windows')) {\n    excludes += [\n        'Listing_12_13_Processes_UnixCommands.groovy',    // runs 'ls' etc.\n        'Listing_12_14_Processes_ZipUnzip.groovy',        // needs gzip/gunzip\n    ]\n}\n//excludes += ['snippet13_googleIpAdr.groovy'] // uncomment if no Internet\n\nnew File('.').traverse(type: FileType.FILES,\n        nameFilter: ~/Listing_.*groovy|snippet.*groovy|extra_.*groovy/) { file ->\n    if (excludes.any { file =~ it }) return\n    if (file.name.contains('Windows_only') && !os.contains('windows')) return\n    if (ver != 1.8 && file.name.contains('_jdk8_only')) return\n    if (ver != 1.7 && file.name.contains('_jdk7_only')) return\n    if (ver != 1.6 && file.name.contains('_jdk6_only')) return\n    if (ver < 1.8 && file.name.contains('_jdk8_plus')) return\n    if (ver < 1.7 && file.name.contains('_jdk7_plus')) return\n\n    println \"evaluating $file\"\n    try {\n        new GroovyShell().run(file)\n        println \"OK\"\n    }\n    catch (Throwable t) {\n        failed << file\n        println \"FAILED \" + t.message\n    }\n}\nfailed.each { print \"\\nFAILED: \" + it }\n"
  }
]