1. Shantanu Kumar
  2. Bituf-Handbook

Commits

kumarshantanu  committed 0404e58

first import

  • Participants
  • Branches default

Comments (0)

Files changed (4)

File build-all.bat

View file
  • Ignore whitespace
+@echo off
+Rem See these links:
+Rem http://www.springfuse.com/blog/docbook/maven-docbook-syntax-highlighting.pdf
+Rem http://code.google.com/p/docbkx-tools/
+Rem http://docbkx-tools.sourceforge.net/docbkx-maven-plugin/plugin-info.html
+
+echo Cleaning up previous build artifacts
+call mvn clean
+
+echo Generating PDF
+call mvn docbkx:generate-pdf
+
+rem echo Generating HTML
+call mvn docbkx:generate-html

File build-all.sh

View file
  • Ignore whitespace
+#!/bin/sh
+# See these links:
+# http://www.springfuse.com/blog/docbook/maven-docbook-syntax-highlighting.pdf
+# http://code.google.com/p/docbkx-tools/
+# http://docbkx-tools.sourceforge.net/docbkx-maven-plugin/plugin-info.html
+
+echo Cleaning up previous build artifacts
+mvn clean
+
+echo Generating PDF
+mvn docbkx:generate-pdf
+
+rem echo Generating HTML
+mvn docbkx:generate-html

File pom.xml

View file
  • Ignore whitespace
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.bituf</groupId>
+  <artifactId>bituf-handbook</artifactId>
+  <version>0.1-SNAPSHOT</version>
+  <name>BitumenFrameworkHandbook</name>
+  <description>The handbook cum user-guide for Bitumen Framework. The raw form contains Docbook content. This project can be run through a Maven build to generate PDF/HTML documents for the handbook.</description>
+  <build>
+    <!-- To define the plugin version in your parent POM -->
+    <!--
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>com.agilejava.docbkx</groupId>
+          <artifactId>docbkx-maven-plugin</artifactId>
+          <version>2.0.11</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    -->
+    <!-- To use the plugin goals in your POM or parent POM -->
+    <plugins>
+      <plugin>
+        <groupId>com.agilejava.docbkx</groupId>
+        <artifactId>docbkx-maven-plugin</artifactId>
+        <version>2.0.11</version>
+      </plugin>
+    </plugins>
+  </build>
+</project>

File src/docbkx/bituf-handbook.xml

View file
  • Ignore whitespace
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<book>
+  <bookinfo>
+    <title>The Bitumen Framework Handbook</title>
+
+    <author>
+      <firstname>Shantanu</firstname>
+
+      <surname>Kumar</surname>
+
+      <affiliation>
+        <orgname>Bitumen Framework
+          <link linkend="http://code.google.com/p/bitumenframework/">
+            http://code.google.com/p/bitumenframework/
+          </link>
+        </orgname>
+      </affiliation><email>kumar.shantanu@gmail.com</email>
+    </author>
+
+    <pubdate>27 Feb 2011</pubdate>
+  </bookinfo>
+
+  <chapter>
+    <title>Introduction</title>
+
+    <section>
+      <title>Premise</title>
+
+      <para><emphasis>The Bitumen Framework Handbook</emphasis> serves as a
+        developer's guide to using Bitumen Framework for developing applications
+        in the Clojure programming language, giving you the knowledge and
+        experience to use it in a wide range of situations.
+      </para>
+
+      <section>
+        <title>What is it?</title>
+
+        <para></para>
+
+        <para>Bitumen Framework<footnote><para>URL:
+          <link linkend="http://code.google.com/p/bitumenframework/">
+          http://code.google.com/p/bitumenframework/
+          </link></para></footnote> is a collection of libraries for developing
+          Clojure<footnote><para><link linkend="http://clojure.org">
+          http://clojure.org</link></para></footnote> applications on the
+          <trademark>Java</trademark> Virtual Machine. This handbook describes
+          how to use those libraries for various use-cases.
+        </para>
+
+        <para>Clojure is a functional Lisp with strong focus on immutability
+        and concurrency. Clojure also has excellent Java interoperability,
+        something that Bitumen Framework libraries use heavily.</para>
+
+        <para></para>
+      </section>
+
+      <section>
+        <title>Intended Audience</title>
+
+        <para>An ideal reader would know enough Clojure to be able to write
+        short programs on her own and try out things on the REPL. She would
+        know general programming and logic concepts. Prior experience in
+        application programming using another language and knowing about
+        Java/JVM to some extent may be helpful.</para>
+      </section>
+    </section>
+
+    <section>
+      <title>How This Handbook Is Organized</title>
+
+      <para>This handbook contains several chapters, each dedicated to one
+        specific library from the Bitumen Framework. They broadly cover the
+        following libraries:
+        <itemizedlist>
+          <listitem><para>Clj-MiscUtil</para></listitem>
+          <listitem><para>Clj-DBSpec</para></listitem>
+          <listitem><para>Clj-DBCP</para></listitem>
+          <listitem><para>Clj-Liquibase</para></listitem>
+          <listitem><para>Fountain-JDBC</para></listitem>
+          <listitem><para>SQLRat</para></listitem>
+        </itemizedlist>
+      </para>
+
+      <section>
+        <title>Description of Libraries</title>
+
+        <para>The libraries listed above serve different purposes toward
+          developing applications. Their description is below.
+        </para>
+        <section>
+          <title>Clj-MiscUtil</title>
+          <para><emphasis>Blurb:</emphasis> Clj-MiscUtil is an assortment of
+            Clojure functions/macros to carry out miscellaneous common activities.
+          </para>
+          <para>Sources:
+            <link linkend="https://bitbucket.org/kumarshantanu/clj-miscutil/src">
+              https://bitbucket.org/kumarshantanu/clj-miscutil/src
+            </link>
+          </para>
+        </section>
+      </section>
+
+      <section>
+        <title>Version matrix</title>
+
+        <para></para>
+      </section>
+    </section>
+
+    <section>
+      <title>Usage Scenarios</title>
+
+      <para></para>
+    </section>
+  </chapter>
+
+  <chapter>
+    <title>Miscellaneous Activities</title>
+
+    <para>This chapter describes the usage of
+    <firstterm>Clj-MiscUtil</firstterm> library for miscellaneous tasks. The
+    tasks are categorized below into sub-sections. Clj-MiscUtil is under the
+    namespace <literal> org.bituf.clj-miscutil</literal> that you can include
+    as follows:</para>
+
+    <programlisting>(use 'org.bituf.clj-miscutil)</programlisting>
+
+    <para>or</para>
+
+    <programlisting>(ns example.app
+  (:require
+    [org.bituf.clj-miscutil :as mu]))</programlisting>
+
+    <para>The examples below assume the first statement.</para>
+
+    <sect1>
+      <title>Random values</title>
+
+      <para>Random numeric and string values may be required for various
+      purposes while programming. The <literal> random-number</literal> and
+      <literal>random-string</literal> functions cater for these.</para>
+
+      <sect2>
+        <title>Generating a random number</title>
+
+        <para>To generate a random number (long), you can use the
+        <literal>random-number</literal> function.</para>
+
+        <programlisting>(random-number)</programlisting>
+
+        <para>Random numbers may be useful to create unique filenames or
+        database table names with a common prefix.</para>
+
+        <para><programlisting>(str "invoices-2011-02-20-" (random-number))</programlisting></para>
+
+        <para>To obtain a random number (double precision) from a certain
+        min/max range, you can specify the range:</para>
+
+        <programlisting>;; return a random number between 10 (included) and 20 (excluded)
+(random-number 10 20)</programlisting>
+
+        <para>For an example, to randomly pick a value from a vector, you
+        would use something like this:</para>
+
+        <programlisting>(let [v [1 2 3 4 5 6 7 8 9]]
+  (v (int (random-number 0 (count v)))))</programlisting>
+      </sect2>
+
+      <sect2>
+        <title>Generating a random string</title>
+
+        <para>Random alphanumeric string can be generated using the
+        <literal>random-string</literal> function that returns string of
+        length 11-13 characters by default. You can optionally specify a
+        length of the random string.</para>
+
+        <programlisting>(random-string)     ; string of random 11-13 characters
+
+(random-string 20)  ; string of 20 random characters</programlisting>
+
+        <para>Another way of generating alphanumeric random characters is to
+        use the <literal>random-charseq</literal> function. By default this
+        function returns a lazy-sequence of infinite alphanumeric characters
+        but you can optionally specify a length.</para>
+
+        <programlisting>(random-charseq)     ; lazy seq of infinite random characters
+
+(random-charseq 10)  ; lazy seq of 10 random characters</programlisting>
+      </sect2>
+    </sect1>
+
+    <sect1>
+      <title>Type checking</title>
+
+      <para>Clojure core has some built in functions to determine the types of
+      values, such as <literal>number?</literal>, <literal> string?</literal>,
+      <literal>map?</literal> etc. Additional such functions not available in
+      Clojure core are below:</para>
+
+      <programlisting>(boolean? false)       ; returns true
+(boolean? "hello")     ; returns false
+
+(not-boolean? "hello") ; returns true
+(not-boolean? true)    ; returns false
+
+(date? (java.util.Date.))      ; returns true
+(date? "hello")                ; returns false
+
+(not-date? (java.util.Date.))  ; returns false
+(not-date? "hello")            ; returns true</programlisting>
+    </sect1>
+
+    <sect1>
+      <title>Pretty printing</title>
+
+      <para>These are some pretty printing functions that you can use:</para>
+      <para><emphasis role="bold"><literal><function>with-stringwriter</function></literal></emphasis></para>
+      <para>This macro is used to assign a StringWriter to specified symbol in a
+      let binding and execute body of code in that context. Returns the string
+      from StringWriter . Example:</para>
+      <programlisting>(with-stringwriter s
+  (.append s "Hello")
+  (.append s "World"))  ; returns "HelloWorld"</programlisting>
+      
+      <para><emphasis role="bold"><literal><function>with-err-str</function></literal></emphasis></para>
+      <para>This macro is like <literal><function>with-out-str</function></literal>
+      but for <literal><function>*err*</function></literal> instead of
+      <literal><function>*out*</function></literal>.</para>
+      
+      <para><emphasis role="bold"><literal><function>pprint-str</function></literal></emphasis></para>
+      
+      <para>This function (accepts one argument) prints anything that you pass
+      to it using <literal><function>clojure.pprint/pprint</function></literal>
+      and returns the result as string.</para>
+      
+      <para><emphasis role="bold"><literal><function>comma-sep-str</function></literal></emphasis></para>
+      
+      <para>This function accepts a collection as argument and returns a comma
+      separated string representation.</para>
+      
+      <para><emphasis role="bold"><literal><function>echo</function></literal></emphasis></para>
+      
+      <para>This function is a simple diagnostic tool that pretty-prints
+      anything (single argument) you pass to it and returns the same argument.</para>
+      
+    </sect1>
+
+    <sect1>
+      <title>Number sign detection</title>
+
+      <para>Detecting sign of numbers may be tricky. <literal>(pos?
+      34)</literal> returns <literal>true</literal> as expected, but
+      <literal>(pos? "Hello")</literal> throws <literal>
+      ClassCastException</literal>. The alternatives below return false in
+      event of exceptions.</para>
+
+      <programlisting>(zeronum? 0)        ; return true
+(zeronum? 36)       ; return false
+(zeronum? "hello")  ; returns false
+
+(posnum? 378)       ; returns true
+(posnum? -32)       ; returns false
+(posnum? :pqrs)     ; returns false
+
+(negnum? 378)       ; returns false
+(negnum? -32)       ; returns true
+(negnum? :pqrs)     ; returns false</programlisting>
+    </sect1>
+
+    <sect1>
+      <title>Print tables</title>
+
+      <para>Printing tables of data is useful for many scenarios. The data to
+      be printed as a table is generally a collection of rows, optionally with
+      a header row. You can use the <literal> print-table</literal> function
+      to print a table of data to <literal>*out*</literal>.</para>
+
+      <programlisting>(print-table [{:a 10 :b 20 :c 30}
+              {:a 40 :b 50 :c 60}
+              {:a 70 :b 80 :c 90}])  ; with titles "a", "b" and "c"
+
+(print-table [[10 20 30]
+              [40 50 60]
+              [70 80 90]])           ; without any titles
+
+(print-table  [:a :b :c]
+             [[10 20 30]
+              [40 50 60]
+              [70 80 90]])           ; with titles "a", "b" and "c"</programlisting>
+
+      <para>The examples above use the defaults to print the tables. You can
+      override the defaults to alter the way tables are printed. For example,
+      every column width is computed by default, if you want to specify width
+      of columns you can use something like this:</para>
+
+      <programlisting>(binding [*pt-cols-width* [5 -1 7]]
+  (print-table [{:id 1001 :name "Harry"    :gender :male}
+                {:id 2997 :name "Samantha" :gender :female}
+                {:id 8328 :name "Christie" :gender :female}]))</programlisting>
+
+      <para>Other options you can override are as follows:</para>
+
+      <programlisting linenumbering="numbered">*pt-column-delim*   -- column delimiter string
+*pt-min-cols-width* -- collection of minimum width for each column
+*pt-max-cols-width* -- collection of maximum width for each column
+*pt-cols-width*     -- collection of numeric width for each column</programlisting>
+
+      <para><emphasis role="bold">Note:</emphasis> One notable feature of
+      <literal>*pt-cols-width*</literal> is that a non-positive number implies
+      that the width would be automatically computed.</para>
+    </sect1>
+
+    <sect1>
+      <title>Var metadata</title>
+
+      <para>Details about vars can be very useful during debugging,
+      diagnostics or error reporting. You can find out the name (string) of a
+      var using the macro <literal>var-name</literal>, fn-body of the var
+      using <literal>var-body</literal> function and type/value of a value
+      using the <literal>val-dump</literal> function.</para>
+
+      <programlisting>(var-name map?)  ; returns "map?"
+
+(var-body map?)  ; returns source code for map? function
+
+(val-dump #"[a-z0-9]")  ; returns type and value as string</programlisting>
+    </sect1>
+
+    <sect1>
+      <title>Throwing exceptions</title>
+
+      <para>Throwing exceptions with sufficient diagnostic context in them is
+      very important for meaningful error reporting. The functions shown below
+      let you throw exceptions with relevant context:</para>
+
+      <informaltable>
+        <tgroup cols="3">
+          <thead>
+            <row>
+              <entry>Function</entry>
+
+              <entry>Which exception</entry>
+
+              <entry>When to use</entry>
+            </row>
+          </thead>
+
+          <tbody>
+            <row>
+              <entry><literal>illegal-arg</literal></entry>
+
+              <entry>IllegalArgumentException</entry>
+
+              <entry>You want to specify the reason as one or more string
+              values</entry>
+            </row>
+
+            <row>
+              <entry><literal>illegal-arg-wrap</literal></entry>
+
+              <entry>IllegalArgumentException</entry>
+
+              <entry>You want to wrap another exception</entry>
+            </row>
+
+            <row>
+              <entry><literal>illegal-argval</literal></entry>
+
+              <entry>IllegalArgumentException</entry>
+
+              <entry>Actual argument is different from expected input</entry>
+            </row>
+
+            <row>
+              <entry><literal>illegal-state</literal></entry>
+
+              <entry>IllegalStateException</entry>
+
+              <entry>You want to specify the reason as one or more string
+              values</entry>
+            </row>
+
+            <row>
+              <entry><literal>illegal-state-wrap</literal></entry>
+
+              <entry>IllegalStateException</entry>
+
+              <entry>You want to wrap another exception</entry>
+            </row>
+
+            <row>
+              <entry><literal>unsupported-op</literal></entry>
+
+              <entry>UnsupportedOperationException</entry>
+
+              <entry>You want to specify the reason as one or more string
+              values</entry>
+            </row>
+
+            <row>
+              <entry><literal>unsupported-op-wrap</literal></entry>
+
+              <entry>UnsupportedOperationException</entry>
+
+              <entry>You want to wrap another exception</entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </informaltable>
+
+      <para>Examples of these functions are as follows:</para>
+
+      <programlisting>(illegal-arg "name should not have more than 3 vowels")
+
+(try (get-fname empname)
+  (catch Exception e
+    (illegal-arg-wrap e (str "bad empname: " empname))))
+
+(illegal-argval "empname" "string having 3 vowels or less" empname)
+
+(illegal-state "Value of x cannot be &gt; " max-x)
+
+;; assuming e is an exception
+(illegal-state-wrap e "Fahrenheit cannot be more than 98.4 degrees")
+
+(unsupported-op "Not yet implemented")
+
+;; assuming e is an exception
+(unsupported-op e "Attempt to carry out activity failed")</programlisting>
+    </sect1>
+
+    <sect1>
+      <title>Non-breaking error handling</title>
+
+      <blockquote><para>This has been discussed
+        <footnote><para>Part 1: <link
+          linkend="http://bitumenframework.blogspot.com/2010/11/non-breaking-error-handling-in-clojure.html"
+          >http://bitumenframework.blogspot.com/2010/11/non-breaking-error-handling-in-clojure.html</link></para>
+        </footnote>
+        <footnote><para>Part 2: <link
+          linkend="http://bitumenframework.blogspot.com/2011/01/non-breaking-error-handling-in-clojure.html"
+          >http://bitumenframework.blogspot.com/2011/01/non-breaking-error-handling-in-clojure.html</link></para>
+        </footnote>
+        on the Bitumen Framework blog.</para>
+      </blockquote>
+      
+      <para>When executing code that might throw an exception we generally
+      wrap it in a try/catch block as we want to deal with the breakage in
+      execution flow. Dealing with execution breakage in-place makes the code
+      imperative and often brittle.</para>
+
+      <sect2>
+        <title>The <literal>maybe</literal> macro family</title>
+
+        <para>The <literal>maybe</literal> macro executes body of code and
+        returns a vector of two elements - the first element being the return
+        value, and the second being the exception.</para>
+
+        <programlisting>(maybe (pos? 648)) ; returns [true nil]
+(maybe (pos? nil)) ; returns [nil &lt;NullPointerException instance&gt;]</programlisting>
+
+        <para>Since <literal>maybe</literal> is a macro you can pass arbitrary
+        body of well-formed code to it and it will consistently return a
+        2-element vector every time. An example usage of
+        <literal>maybe</literal> is as follows:</para>
+
+        <programlisting>(doseq [[ret ex] (map #(maybe (process-order %)) orders)]
+  (or ret (log/success ret))
+  (or ex  (do (log/error ex)
+            (trigger-alert ex))))</programlisting>
+
+        <para>There are two close cousins of the <literal> maybe</literal>
+        macro, called <literal>maybe-ret</literal> (gets the return value, or
+        <literal>nil</literal> when an exception is thrown) and
+        <literal>maybe-ex</literal> (gets the exception, or
+        <literal>nil</literal> when no exception is thrown).</para>
+
+        <programlisting>(maybe-ret (Integer/parseInt "45"))    ; returns 45
+(maybe-ret (Integer/parseInt "hello")) ; returns nil
+
+(maybe-ex (Integer/parseInt "45"))     ; returns nil
+(maybe-ex (Integer/parseInt "hello"))  ; returns NumberFormatException</programlisting>
+      </sect2>
+
+      <sect2>
+        <title>Selectively uphold or ignore exceptions</title>
+
+        <para>At times we may need to ignore or uphold exceptions based on the
+        context. The macros <literal>filter-exception</literal> (takes a
+        predicate function) and <literal> with-exceptions</literal> (takes
+        list of exceptions to uphold and ignore) let us do exactly that. Both
+        macros return <literal> nil</literal> when an exception is
+        ignored.</para>
+
+        <para>When you need arbitrary control over how/when to filter an
+        exception you can use <literal> filter-exception</literal>.</para>
+
+        <programlisting>(filter-exception #(instance? ClassCastException %)
+  (pos? "hello"))  ; returns nil</programlisting>
+
+        <para>Another situation is when you know beforehand which exceptions
+        to uphold and which ones to ignore.</para>
+
+        <programlisting>;; throws exception
+(with-exceptions [IllegalArgumentException IllegalStateException]
+                 [RuntimeException]
+  "foo" ; non-effective return value
+  (throw (IllegalArgumentException. "dummy")))
+
+;; swallows exception
+(with-exceptions [IllegalArgumentException IllegalStateException]
+                 [RuntimeException]
+  "foo" ; non-effective return value
+  (throw (NullPointerException. "dummy")))</programlisting>
+
+      </sect2>
+    </sect1>
+
+    <sect1>
+      <title>Type conversion</title>
+
+      <para>Type conversion is one of the most frequent needs during data
+      processing. The table below describes which function converts to which
+      type. All functions in this section accept input in various formats and
+      try to coerce the input into desired type.</para>
+
+      <informaltable>
+        <tgroup cols="4">
+          <colspec colname="c1" />
+
+          <colspec colname="c2" />
+
+          <colspec colname="c3" />
+
+          <colspec colname="c4" />
+
+          <thead>
+            <row>
+              <entry align="center">Function</entry>
+
+              <entry align="center">Converts to</entry>
+
+              <entry align="center" nameend="c4" namest="c3">Remarks</entry>
+            </row>
+          </thead>
+
+          <tbody>
+            <row>
+              <entry><literal>as-string</literal></entry>
+
+              <entry>string</entry>
+
+              <entry nameend="c4" namest="c3">converts anything to string
+              (i.e. <literal>:key</literal> becomes <literal>
+              "key"</literal>)</entry>
+            </row>
+
+            <row>
+              <entry><literal>java-filename</literal></entry>
+
+              <entry>string</entry>
+
+              <entry nameend="c4" namest="c3">Replaces path separators in
+              supplied filename with Java-compatible platform independent
+              separator</entry>
+            </row>
+
+            <row>
+              <entry><literal>as-vstr</literal></entry>
+
+              <entry>string</entry>
+
+              <entry nameend="c4" namest="c3">Verbose string (i.e.
+              <literal>nil</literal> becomes <literal>
+              "&lt;nil&gt;"</literal>)</entry>
+            </row>
+
+            <row>
+              <entry><literal>as-keys</literal></entry>
+
+              <entry>collection</entry>
+
+              <entry nameend="c4" namest="c3">Gets keys of a map, or the
+              entire collection if not a map</entry>
+            </row>
+
+            <row>
+              <entry><literal>as-vals</literal></entry>
+
+              <entry>collection</entry>
+
+              <entry nameend="c4" namest="c3">Gets vals of map, or the entire
+              collection of not a map</entry>
+            </row>
+
+            <row>
+              <entry><literal>as-vector</literal></entry>
+
+              <entry>vector</entry>
+
+              <entry nameend="c4" namest="c3">Turns anything into a
+              vector</entry>
+            </row>
+
+            <row>
+              <entry><literal>as-set</literal></entry>
+
+              <entry>set</entry>
+
+              <entry nameend="c4" namest="c3">Turns anything into a
+              set</entry>
+            </row>
+
+            <row>
+              <entry><literal>as-map</literal></entry>
+
+              <entry>map</entry>
+
+              <entry nameend="c4" namest="c3">Turns anything into a
+              map</entry>
+            </row>
+
+            <row>
+              <entry><literal>coerce</literal></entry>
+
+              <entry>depends on the predicate function</entry>
+
+              <entry nameend="c4" namest="c3">Coerces value using a predicate
+              function</entry>
+            </row>
+
+            <row>
+              <entry><literal>as-boolean</literal></entry>
+
+              <entry>boolean</entry>
+
+              <entry nameend="c4" namest="c3">Parses anything as
+              boolean</entry>
+            </row>
+
+            <row>
+              <entry><literal>as-short</literal></entry>
+
+              <entry>short integer</entry>
+
+              <entry nameend="c4" namest="c3">Parses anything as short</entry>
+            </row>
+
+            <row>
+              <entry><literal>as-integer</literal></entry>
+
+              <entry>integer</entry>
+
+              <entry nameend="c4" namest="c3">Parses anything as
+              integer</entry>
+            </row>
+
+            <row>
+              <entry><literal>as-long</literal></entry>
+
+              <entry>long integer</entry>
+
+              <entry nameend="c4" namest="c3">Parses anything as long</entry>
+            </row>
+
+            <row>
+              <entry><literal>as-float</literal></entry>
+
+              <entry>float</entry>
+
+              <entry nameend="c4" namest="c3">Parses anything as float</entry>
+            </row>
+
+            <row>
+              <entry><literal>as-double</literal></entry>
+
+              <entry>double</entry>
+
+              <entry nameend="c4" namest="c3">Parses anything as
+              double</entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </informaltable>
+    </sect1>
+
+    <sect1>
+      <title>`<literal>not-</literal>` associated functions</title>
+
+      <para>Quite often we use a <literal>(not ..)</literal> version of a
+      boolean function, e.g. <literal>(not (map? foo))</literal> while
+      checking for conditions. The functions listed below are shorthand of
+      using with <literal>not</literal>:</para>
+
+      <informaltable>
+        <tgroup cols="4">
+          <thead>
+            <row>
+              <entry align="center">Function==&gt;</entry>
+
+              <entry align="center">Counterpart in clojure.core</entry>
+
+              <entry align="center">Function==&gt;</entry>
+
+              <entry align="center">Counterpart in clojure.core</entry>
+            </row>
+          </thead>
+
+          <tbody>
+            <row>
+              <entry><literal>any?</literal></entry>
+
+              <entry><literal>not-any?</literal></entry>
+
+              <entry><literal>not-associative?</literal></entry>
+
+              <entry><literal>associative?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-bound?</literal></entry>
+
+              <entry><literal>bound?</literal></entry>
+
+              <entry><literal>not-char?</literal></entry>
+
+              <entry><literal>char?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-chunked-seq?</literal></entry>
+
+              <entry><literal>chunked-seq?</literal></entry>
+
+              <entry><literal>not-class?</literal></entry>
+
+              <entry><literal>class?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-coll?</literal></entry>
+
+              <entry><literal>coll?</literal></entry>
+
+              <entry><literal>not-contains?</literal></entry>
+
+              <entry><literal>contains?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-counted?</literal></entry>
+
+              <entry><literal>counted?</literal></entry>
+
+              <entry><literal>not-decimal?</literal></entry>
+
+              <entry><literal>decimal?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-delay?</literal></entry>
+
+              <entry><literal>delay?</literal></entry>
+
+              <entry><literal>not-distinct?</literal></entry>
+
+              <entry><literal>distinct?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-empty?</literal></entry>
+
+              <entry><literal>empty?</literal></entry>
+
+              <entry><literal>not-even?</literal></entry>
+
+              <entry><literal>even?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-extends?</literal></entry>
+
+              <entry><literal>extends?</literal></entry>
+
+              <entry><literal>not-false?</literal></entry>
+
+              <entry><literal>false?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-float?</literal></entry>
+
+              <entry><literal>float?</literal></entry>
+
+              <entry><literal>not-fn?</literal></entry>
+
+              <entry><literal>fn?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-future-cancelled?</literal></entry>
+
+              <entry><literal>future-cancelled?</literal></entry>
+
+              <entry><literal>not-future-done?</literal></entry>
+
+              <entry><literal>future-done?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-future?</literal></entry>
+
+              <entry><literal>future?</literal></entry>
+
+              <entry><literal>not-identical?</literal></entry>
+
+              <entry><literal>identical?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-ifn?</literal></entry>
+
+              <entry><literal>ifn?</literal></entry>
+
+              <entry><literal>not-instance?</literal></entry>
+
+              <entry><literal>instance?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-integer?</literal></entry>
+
+              <entry><literal>integer?</literal></entry>
+
+              <entry><literal>not-isa?</literal></entry>
+
+              <entry><literal>isa?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-keyword?</literal></entry>
+
+              <entry><literal>keyword?</literal></entry>
+
+              <entry><literal>not-list?</literal></entry>
+
+              <entry><literal>list?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-map?</literal></entry>
+
+              <entry><literal>map?</literal></entry>
+
+              <entry><literal>not-neg?</literal></entry>
+
+              <entry><literal>neg?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-nil?</literal></entry>
+
+              <entry><literal>nil?</literal></entry>
+
+              <entry><literal>not-number?</literal></entry>
+
+              <entry><literal>number?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-odd?</literal></entry>
+
+              <entry><literal>odd?</literal></entry>
+
+              <entry><literal>not-pos?</literal></entry>
+
+              <entry><literal>pos?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-ratio?</literal></entry>
+
+              <entry><literal>ratio?</literal></entry>
+
+              <entry><literal>not-rational?</literal></entry>
+
+              <entry><literal>rational?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-reversible?</literal></entry>
+
+              <entry><literal>reversible?</literal></entry>
+
+              <entry><literal>not-satisfies?</literal></entry>
+
+              <entry><literal>satisfies?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-seq?</literal></entry>
+
+              <entry><literal>seq?</literal></entry>
+
+              <entry><literal>not-sequential?</literal></entry>
+
+              <entry><literal>sequential?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-set?</literal></entry>
+
+              <entry><literal>set?</literal></entry>
+
+              <entry><literal>not-sorted?</literal></entry>
+
+              <entry><literal>sorted?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-special-symbol?</literal></entry>
+
+              <entry><literal>special-symbol?</literal></entry>
+
+              <entry><literal>not-string?</literal></entry>
+
+              <entry><literal>string?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-symbol?</literal></entry>
+
+              <entry><literal>symbol?</literal></entry>
+
+              <entry><literal>not-thread-bound?</literal></entry>
+
+              <entry><literal>thread-bound?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-true?</literal></entry>
+
+              <entry><literal>true?</literal></entry>
+
+              <entry><literal>not-var?</literal></entry>
+
+              <entry><literal>var?</literal></entry>
+            </row>
+
+            <row>
+              <entry><literal>not-vector?</literal></entry>
+
+              <entry><literal>vector?</literal></entry>
+
+              <entry><literal>not-zero?</literal></entry>
+
+              <entry><literal>zero?</literal></entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </informaltable>
+    </sect1>
+
+    <sect1>
+      <title>Map transformation</title>
+
+      <para>Transforming collections can be easily done using <literal>
+      map</literal> or <literal>for</literal>. However, transforming maps
+      always involves destructuring the key and value and then apply any
+      transformation. The functions <literal> map-keys</literal> and
+      <literal>map-vals</literal> let you simply transform either the keys or
+      the values of a map. When using <literal>map-keys</literal> you must
+      ensure that the transformed set of keys are unique.</para>
+
+      <programlisting>(map-keys inc (array-map 1 2 3 4 5 6)) ; returns {2 2 4 4 6 6}
+
+(map-vals dec (array-map 1 2 3 4 5 6)) ; returns {1 1 3 3 5 5}</programlisting>
+    </sect1>
+
+    <sect1>
+      <title>Array types</title>
+
+      <para>Dealing with arrays may become unavoidable when working with Java
+      libraries. The following functions may help:</para>
+
+      <para><emphasis role="bold">array-type</emphasis></para>
+
+      <para><literal><function>array-type</function></literal> returns the
+      common type (class) of elements that can be contained in the
+      array.</para>
+
+      <para><emphasis
+      role="bold"><literal><function>array?</function></literal></emphasis></para>
+
+      <para><literal><function>array?</function></literal> returns true if the
+      argument is an array, false otherwise.</para>
+
+      <para><emphasis
+      role="bold"><literal><function>not-array?</function></literal></emphasis></para>
+
+      <para><literal><function>not-array?</function></literal> is same as
+      <literal><function>(not (array? foo))</function></literal>.</para>
+    </sect1>
+
+    <sect1>
+      <title>`<literal>contains-val?</literal>` : `<literal>contains?</literal>` for value</title>
+
+      <para>The <literal>contains?</literal> function in clojure.core looks
+      for a key in a collection. For a vector the keys are the indices, for
+      sets they are the elements and for maps they are keys. The
+      <literal>contains-val?</literal> function looks for values instead of
+      keys.</para>
+
+      <programlisting>(contains?     [:a :b :c] :b) ; returns false
+(contains-val? [:a :b :c] :b) ; returns true
+
+(contains?     {:a 10 :b 20} 20) ; returns false
+(contains-val? {:a 10 :b 20} 20) ; returns true</programlisting>
+    </sect1>
+
+    <sect1>
+      <title>Stack trace and Exceptions</title>
+
+      <blockquote><para>This concept has been discussed<footnote>
+        <para>URL:<link
+          linkend="http://bitumenframework.blogspot.com/2010/10/stack-traces-for-clojure-app.html"
+          >http://bitumenframework.blogspot.com/2010/10/stack-traces-for-clojure-app.html</link>
+        </para></footnote>
+        on the Bitumen Framework Blog.</para>
+      </blockquote>
+      
+      <para>Exception stack trace for Clojure code usually includes quite some
+      unwanted entries, which are not very useful while debugging and rather
+      clutter the view. The function
+      <literal><function>print-exception-stacktrace</function></literal>
+      can be used to print an exception stack trace with reduced clutter. It
+      falls back to the following as stack trace elements (in that order):
+      <simplelist>
+        <member>1. Application code and Dependencies (without Clojure core/contrib or Java code)</member>
+        <member>2. Clojure core/contrib and application code (without Java code)</member>
+        <member>3. All Java and Clojure code (everything)</member>
+      </simplelist></para>
+      <para>When trying this on the REPL with Clojure core/contrib libraries,
+      you may not encounter #1 in the stack trace.</para>
+      <para>There are two convenience macros - <literal>!</literal> and
+      <literal>!!</literal> that accept a body of code and print friendly stack
+      trace if there is any exception. The difference between the two is that
+      <literal>!</literal> prints only required columns of the stack trace and
+      <literal>!!</literal> prints an additional IDE Reference column to
+      generate filenames clickable within the IDE (tested on Eclipse and IDEA).
+      Example is below:</para>
+      <programlisting>(! (foo arg))   ; prints normal stack-trace columns
+
+(!! (foo arg))  ; prints extra IDE reference column</programlisting>
+    </sect1>
+
+    <sect1>
+      <title>Assertion helpers</title>
+
+      <para><emphasis role="bold"><literal><function>verify-arg</function></literal></emphasis></para>
+      <para>Throws IllegalArgumentException if body of code does not return true.</para>
+      <programlisting>(verify-arg (map? arg)) ; verifies arg is a map</programlisting>
+      
+      <para><emphasis role="bold"><literal><function>verify-type</function></literal></emphasis></para>
+      <para>Throws IllegalArgumentException if argument does not match expected type.</para>
+      <programlisting>(verify-type java.util.Date join-date)</programlisting>
+      
+      <para><emphasis role="bold"><literal><function>verify-cond</function></literal></emphasis></para>
+      <para>This macro is same as <literal><function>verify-arg</function></literal>
+      but throws IllegalStateException instead of IllegalArgumentException.</para>
+      
+      <para><emphasis role="bold"><literal><function>verify-opt</function></literal></emphasis></para>
+      <para>This function ensures that only permitted optional arguments are passed
+      as optional arguments to a function or macro.</para>
+      <programlisting>(defn foo
+  [arg &amp; {:keys [a b] :as opt}] {:pre [(verify-opt [:a :b] opt)]}
+  ...)</programlisting>
+      
+    </sect1>
+
+    <sect1>
+      <title>Type annotation</title>
+
+      <blockquote><para>This topic has been discussed<footnote><para>URL:<link
+        linkend="http://bitumenframework.blogspot.com/2010/10/typed-abstractions-in-clojure.html"
+        >http://bitumenframework.blogspot.com/2010/10/typed-abstractions-in-clojure.html</link>
+        </para></footnote> on the Bitumen Framework blog.</para>
+      </blockquote>
+      
+      <para>Type annotation is a way to inject type metadata into regular objects
+        without altering their content. The type metadata can be read back later
+        to act upon them in different ways.
+      </para>
+      <sect2>
+        <title>Annotating with types</title>
+        <para>The following functions help you annotate objects with type metadata:</para>
+        <para><emphasis role="bold">typed</emphasis></para>
+        <para>This function annotates an object with specified type(s), e.g.</para>
+        <para><programlisting>(typed [:argentina :spain]
+  :speaks-spanish)                 ; tag the object with one type
+
+(typed {:name "Henry"
+        :age   23
+        :place "Connecticut"}
+  :person-data :has-age :has-name) ; tag object with multiple types
+
+(typed 65 :average-weight)         ; throws exception - 65 is not object</programlisting></para>
+        <para><emphasis role="bold">ftyped</emphasis></para>
+        <para>For non-objects such as numbers, string, date etc. we need to use
+          <literal>ftyped</literal> so that they can be coerced as objects before
+          they are type-annotated, e.g.
+          <programlisting>(ftyped 65 :average-weight)        ; this works fine</programlisting>
+          <emphasis>Note:</emphasis>Objects created using <literal>ftyped</literal>
+          are no-arg functions that must be executed to return the wrapped value, e.g.
+          <programlisting>(let [d (ftyped 60 :retirement-age)] (d))</programlisting>
+        </para>
+        <para><emphasis role="bold">obj?</emphasis></para>
+        <para><emphasis role="bold">not-obj?</emphasis></para>
+        <para>These functions tell whether a value is an object (i.e. whether it
+          implements the IObject protocol) or not. Only such objects can be
+          annotated with type metadata.
+        </para>
+      </sect2>
+      
+      <sect2>
+        <title>Reading the types back</title>
+        <para><emphasis role="bold">type-meta</emphasis></para>
+        <para>This function returns the type metadata of an object
+          <programlisting>(type-meta (typed {:order-id 34}
+             :pending))              ; returns :pending
+
+(type-meta (typed [:france :germany]
+             :european :countries))  ; returns [:european :countries]
+
+(type-meta (typed (typed [10 20]
+                    :numbers)
+             :sample))               ; returns [:numbers :sample]</programlisting>
+        </para>
+      </sect2>
+      <sect2>
+        <title>Type hierarchies and implied types</title>
+        <blockquote>
+          <para><emphasis>Note:</emphasis> The type and hierarchy system
+            described here works in conjunction with <literal>type</literal> and
+            <literal>isa?</literal> functions and integrates with Clojure multi-methods
+            <footnote><para>URL:<link
+              linkend="http://clojure.org/multimethods"
+              >http://clojure.org/multimethods</link></para>
+            </footnote>
+            <footnote><para>URL:<link
+              linkend="http://dosync.posterous.com/beyond-javascript-prototype-chains"
+              >http://dosync.posterous.com/beyond-javascript-prototype-chains</link></para>
+            </footnote>.
+          </para>
+        </blockquote>
+        <para>Clojure has a built-in feature of type annotation and hierarchy
+          independent of the objects themselves. It means objects are not
+          hard-bound to the types (as in classes, e.g. Java) and type hierarchies
+          can be applied at runtime. This feature enables multiple-inheritance of
+          types in Clojure. See this example:
+          <programlisting>(derive ::employee ::salaried) ; employee is salaried
+(derive ::salaried ::person)   ; salaried is a person
+
+;; returns true because ::employee is both ::salaried and ::person
+(every? #(typed? (typed {:id 3964 :name "Joe"}
+                   ::employee) %)
+  [::salaried ::person])
+
+;; returns true because ::employee is at least ::person
+(some   #(typed? (typed {:id 9604 :name "Cher"}
+                   ::employee) %)
+  [::freelancer ::person])</programlisting>
+        </para>
+        <para><emphasis role="bold">typed?</emphasis></para>
+        <para>You would notice that the code snippet makes use of the function
+          <literal>typed?</literal>, which returns true if the object is of
+          specified type. It internally makes use of the <literal>isa?</literal>
+          function that knows about the specified and global hierarchies.
+        </para>
+      </sect2>
+    </sect1>
+
+    <sect1>
+      <title>Keyword/String conversion</title>
+
+      <para>The keyword/string conversion functions would be best shown with
+        examples:
+        <programlisting>(k-to-camelstr :to-do) ; returns "toDo"
+(camelstr-to-k "toDo") ; returns :to-do
+
+(k-to-methodname :to-do ["add"]) ; returns "addToDo" (now see k-to-camelstr)
+(k-to-setter :price)       ; returns "setPrice"
+(k-to-setter :set-price)   ; returns "setPrice" (detects "set", no repeat)
+(k-to-getter :price)       ; returns "getPrice"
+(k-to-getter :get-price)   ; returns "getPrice"  (detects "get", no repeat)
+(k-to-getter :is-in-stock) ; returns "isInStock" (detects "is" too)
+
+(coll-as-string [:a :b :c])    ; returns ["a" "b" "c"]
+(coll-as-keys   ["a" "b" "c"]) ; returns [:a :b :c]
+(keys-to-str {:a 10 :b 20})    ; returns {"a" 10 "b" 20}
+(str-to-keys {"a" 10 "b" 20})  ; returns {:a 10 :b 20}</programlisting>
+      </para>
+    </sect1>
+
+    <sect1>
+      <title>Reflection (not for performance-critical code)</title>
+
+      <para>The examples below show how to use the API:
+        <programlisting></programlisting>
+      </para>
+      
+      <sect2>
+        <title>Call Java methods</title>
+        <programlisting>(method "Hello" :char-at 0) ; .charAt(0) - returns \H
+
+(method (call-specs "Hello"
+          [:char-at 0]     ; .charAt(0)       - returns \H
+          [:substring 3 4] ; .substring(3, 4) - returns "l"
+          [:to-string]     ; .toString()      - returns "Hello"
+          ))
+
+(map (pojo-fn "Hello") [[:char-at 0]     ; returns primitive char
+                        [:substring 3 4] ; returns string
+                        [:to-string]     ; no-arg method
+                        ]) ; returns lazy (\H "l" "Hello")</programlisting>
+      </sect2>
+      
+      <sect2>
+        <title>Call Java setter methods</title>
+        <programlisting>(setter (StringBuilder.)
+  :length 0) ; .setLength(0) - returns void, 'setter' returns nil
+
+(setter (call-specs sb
+          [:length 4]     ; .setLength(4)      - returns void
+          [:char-at 0 \C] ; .setCharAt(0, 'C') - returns void
+          )) ; 'setter' returns [nil nil]
+
+(map (setter-fn sb) [[:length 4]     ; .setLength(4)      - returns void
+                     [:char-at 0 \C] ; .setCharAt(0, 'C') - returns void
+                     ]) ; returns lazy (nil nil)</programlisting>
+      </sect2>
+      
+      <sect2>
+        <title>Call Java getter methods</title>
+        <programlisting>(let [lst (java.util.LinkedList.)
+      _   (.add lst 1)
+      _   (.add lst 2)]
+  (getter lst :first) ; .getFirst() - returns 1
+  (getter (call-specs lst :first ; .getFirst() - returns 1
+                          :last  ; .getLast()  - returns 2
+                          )) ; returns [1 2]
+  (map (getter-fn lst) [:first ; .getFirst() - returns 1
+                        :last  ; .getLast()  - returns 2
+                        ])) ; returns lazy (1 2)</programlisting>
+      </sect2>
+    </sect1>
+
+    <sect1>
+      <title>java.util.Properties handling</title>
+
+      <para>Assuming that the file sample.properties has the following content:
+        <programlisting>a=10
+b=20
+c=true</programlisting>
+        Properties can be transformed into maps:
+        <programlisting>(let [ps (read-properties "src/test/conf/sample.properties")]
+  (property-map ps)     ; returns {"a" "10" "b" "20" "c" "true"}
+  (strkey-to-keyword
+    (property-map ps))) ; returns {:a "10" :b "20" :c "true"}
+
+(is-true? "true") ; returns true (useful to test bool values in properties)</programlisting>
+      </para>
+    </sect1>
+
+    <sect1>
+      <title>JNDI functions</title>
+
+      <para>
+        These JNDI tree-printing functions can be used to debug the JNDI
+        configuration:
+        <programlisting>(print-jndi-tree) ; print the JNDI tree referring initial context
+
+(find-jndi-subcontext (javax.naming.InitialContext.)
+         "java:comp") ; returns javax.naming.Context (if configured)
+
+(jndi-lookup
+  "java:comp/env/myDataSource") ; returns javax.sql.DataSource (if configured)</programlisting>
+      </para>
+    </sect1>
+  </chapter>
+
+  <chapter>
+    <title>Using RDBMS - Essentials</title>
+
+    <para>ddhd</para>
+
+    <section>
+      <title>Configuration</title>
+
+      <para></para>
+    </section>
+
+    <section>
+      <title>Connection Pooling</title>
+
+      <para></para>
+    </section>
+
+    <section>
+      <title>Simple SQL</title>
+
+      <para></para>
+    </section>
+
+    <section>
+      <title>Parameterized SQL</title>
+
+      <para></para>
+    </section>
+
+    <section>
+      <title>CRUD - Create, Retrieve, Update, Delete</title>
+
+      <para></para>
+    </section>
+
+    <section>
+      <title>Batch Operations</title>
+
+      <para></para>
+    </section>
+
+    <section>
+      <title>Stored Procedures/Functions</title>
+
+      <para></para>
+
+      <section>
+        <title>Parameters to Stored Procedures</title>
+
+        <para></para>
+      </section>
+    </section>
+
+    <section>
+      <title>Error handling and Recovery</title>
+
+      <para></para>
+
+      <section>
+        <title>Exceptions</title>
+
+        <para></para>
+      </section>
+
+      <section>
+        <title>Vendor specific Error Codes</title>
+
+        <para></para>
+      </section>
+    </section>
+  </chapter>
+
+  <chapter>
+    <title>Using RDBMS - Transactions</title>
+
+    <section>
+      <title>Programmatic Transactions</title>
+
+      <para></para>
+    </section>
+
+    <section>
+      <title>Isolation Levels</title>
+
+      <para></para>
+    </section>
+
+    <section>
+      <title>Declarative Transactions</title>
+
+      <para></para>
+    </section>
+  </chapter>
+
+  <chapter>
+    <title>Using RDBMS - Migrations</title>
+
+    <para></para>
+
+    <para></para>
+  </chapter>
+
+  <chapter>
+    <title>Using RDBMS - Entities</title>
+
+    <para></para>
+  </chapter>
+
+  <chapter>
+    <title>Text Templates</title>
+
+    <para></para>
+  </chapter>
+</book>