deltacloud-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Michal Fojtik ...@mifo.sk>
Subject Re: [PATCH] dmtf reference implementation initial checkin
Date Wed, 21 Sep 2011 22:02:36 GMT
On Sep 21, 2011, at 8:42 PM, Tong Li wrote:

Hi Tong Li and welcome aboard!

I went through your code (at least to the half of it) and I have some doubts/suggestion for you:

1. In Ruby, it's more common to use method names like 'method_name' instead of 'methodName'.

2. A lot of debugging code (puts, inspect..), I stopped marking that in the half of your code.
   Please remove this before we commit this code to our repo. Or if you still want to use it,
   I pushed 'sinatra_verbose' module few days before. This gives you helpers like 'debug' and 'info'
   you can use for debugging.
   All the code written down to console usually confuses people and has less or no meaning to people
   who did not originally write that code.

3. I would like to suggest to use 'is_valid?' method rather than 'IsValid'. 
   Also, if you have a method that is not returning anything, use 'method_name!' instead of 'method_name'.
   This usually confuses people (at least me ;) because they expect something is returned and the return 
   value is dropped for some reason ;-) (long story short, it looks like a bug ;-))

I marked examples of above inline in the code bellow.

I'll continue reviewing this patch tomorrow since its pretty late for me already ;-)

PS: Please don't take these suggestions wrong, the main goal to do these reviews is to keep our code
    clean for community or potential future contributors.
    If you have any question, you can find me on #deltacloud channel @ free node (nick: mfojtik).

 -- Michal

> From: tong li <litong01@us.ibm.com>
> 
> ---
> .gitignore                                         |    1 +
> server/bin/deltacloudd                             |    3 +
> server/config.ru                                   |    8 +-
> server/lib/cimi/data/collections/event.col.xml     |   10 +
> server/lib/cimi/data/collections/eventLog.col.xml  |   10 +
> server/lib/cimi/data/collections/job.col.xml       |   10 +
> server/lib/cimi/data/collections/machine.col.xml   |   11 +
> .../lib/cimi/data/collections/machineAdmin.col.xml |   11 +
> .../cimi/data/collections/machineConfig.col.xml    |    1 +
> .../data/collections/machineConfiguration.col.xml  |   12 +
> .../lib/cimi/data/collections/machineImage.col.xml |   11 +
> .../cimi/data/collections/machineTemplate.col.xml  |    1 +
> server/lib/cimi/data/collections/meter.col.xml     |   11 +
> .../cimi/data/collections/meterTemplate.col.xml    |   11 +
> server/lib/cimi/data/collections/network.col.xml   |   11 +
> .../cimi/data/collections/networkConfig.col.xml    |   11 +
> .../cimi/data/collections/networkTemplate.col.xml  |   11 +
> server/lib/cimi/data/collections/system.col.xml    |    1 +
> .../cimi/data/collections/systemTemplate.col.xml   |    6 +
> server/lib/cimi/data/collections/volume.col.xml    |   11 +
> .../data/collections/volumeConfiguration.col.xml   |    1 +
> .../lib/cimi/data/collections/volumeImage.col.xml  |   11 +
> .../cimi/data/collections/volumeTemplate.col.xml   |    1 +
> server/lib/cimi/data/collections/vsp.col.xml       |   11 +
> server/lib/cimi/data/collections/vspConfig.col.xml |   11 +
> .../lib/cimi/data/collections/vspTemplate.col.xml  |    1 +
> .../lib/cimi/data/defaultRes/machineAdmin.col.xml  |   11 +
> .../data/defaultRes/machineConfiguration.col.xml   |   17 +
> .../cimi/data/defaultRes/machineTemplate.col.xml   |   12 +
> server/lib/cimi/data/defaultRes/system.col.xml     |   12 +
> .../cimi/data/defaultRes/systemTemplate.col.xml    |   10 +
> .../data/defaultRes/volumeConfiguration.col.xml    |   14 +
> server/lib/cimi/helpers/cmwgapp_helper.rb          |  352 ++++++
> server/lib/cimi/helpers/cmwgres_helper.rb          |   38 +
> server/lib/cimi/helpers/dmtfdep.rb                 |   44 +
> server/lib/cimi/server.rb                          |  267 +++++
> server/lib/deltacloud/base_driver/base_driver.rb   |    2 +-
> server/lib/deltacloud/server.rb                    | 1191 ++++++++++++++++++++
> server/lib/sinatra/rack_syslog.rb                  |    2 +-
> server/public/images/bread-bg.png                  |  Bin 0 -> 257 bytes
> server/public/images/logo-wide.png                 |  Bin 0 -> 8333 bytes
> server/public/images/topbar-bg.png                 |  Bin 0 -> 72084 bytes
> server/public/javascripts/cmwgapp.js               |  249 ++++
> server/public/javascripts/jquery-1.4.2.min.js      |  154 +++
> server/server.rb                                   | 1191 --------------------
> server/tests/common.rb                             |    3 +-
> server/views/cimi/cloudEntryPoint/index.html.haml  |    7 +
> server/views/cimi/cloudEntryPoint/index.xml.haml   |   10 +
> server/views/cimi/collection/index.html.haml       |   74 ++
> server/views/cimi/collection/response.xml.haml     |    3 +
> server/views/cimi/error.html.haml                  |   31 +
> server/views/cimi/errors/400.html.haml             |   41 +
> server/views/cimi/errors/400.xml.haml              |    4 +
> server/views/cimi/errors/401.html.haml             |   41 +
> server/views/cimi/errors/401.xml.haml              |    3 +
> server/views/cimi/errors/403.html.haml             |   42 +
> server/views/cimi/errors/403.xml.haml              |    2 +
> server/views/cimi/errors/404.html.haml             |   29 +
> server/views/cimi/errors/404.xml.haml              |    2 +
> server/views/cimi/errors/405.html.haml             |   29 +
> server/views/cimi/errors/405.xml.haml              |    5 +
> server/views/cimi/errors/500.html.haml             |   43 +
> server/views/cimi/errors/500.xml.haml              |    5 +
> server/views/cimi/errors/502.html.haml             |   43 +
> server/views/cimi/errors/502.xml.haml              |    7 +
> .../errors/backend_capability_failure.html.haml    |   29 +
> server/views/cimi/layout.html.haml                 |   32 +
> server/views/cimi/machine/index.html.haml          |   35 +
> server/views/cimi/machine/index.json.haml          |    6 +
> server/views/cimi/machine/index.xml.haml           |    6 +
> .../views/cimi/machine/instanceToImage.html.haml   |   32 +
> server/views/cimi/machine/new.html.haml            |   87 ++
> server/views/cimi/machine/operation.html.haml      |    1 +
> server/views/cimi/machine/operation.json.haml      |    3 +
> server/views/cimi/machine/operation.xml.haml       |    3 +
> server/views/cimi/machine/show.html.haml           |   59 +
> server/views/cimi/machine/show.json.haml           |   24 +
> server/views/cimi/machine/show.xml.haml            |   24 +
> server/views/cimi/machineAdmin/new.html.haml       |   47 +
> server/views/cimi/machineAdmin/show.html.haml      |   47 +
> .../views/cimi/machineConfiguration/new.html.haml  |  161 +++
> .../views/cimi/machineConfiguration/show.html.haml |  160 +++
> .../views/cimi/machineConfiguration/show.xml.haml  |   13 +
> server/views/cimi/machineImage/index.html.haml     |   25 +
> server/views/cimi/machineImage/index.json.haml     |    6 +
> server/views/cimi/machineImage/index.xml.haml      |    6 +
> server/views/cimi/machineImage/show.html.haml      |   21 +
> server/views/cimi/machineImage/show.json.haml      |   10 +
> server/views/cimi/machineImage/show.xml.haml       |   10 +
> server/views/cimi/machineTemplate/new.html.haml    |   79 ++
> server/views/cimi/machineTemplate/show.html.haml   |   79 ++
> server/views/cimi/system/new.html.haml             |   80 ++
> server/views/cimi/system/show.html.haml            |   80 ++
> server/views/cimi/system/show.xml.haml             |   11 +
> server/views/cimi/systemTemplate/new.html.haml     |   70 ++
> server/views/cimi/systemTemplate/show.html.haml    |   71 ++
> server/views/cimi/test/index.haml                  |    9 +
> server/views/cimi/test/index.html.haml             |   20 +
> .../views/cimi/volumeConfiguration/new.html.haml   |   75 ++
> .../views/cimi/volumeConfiguration/show.html.haml  |   77 ++
> 100 files changed, 4489 insertions(+), 1197 deletions(-)
> create mode 100644 server/lib/cimi/data/collections/event.col.xml
> create mode 100644 server/lib/cimi/data/collections/eventLog.col.xml
> create mode 100644 server/lib/cimi/data/collections/job.col.xml
> create mode 100644 server/lib/cimi/data/collections/machine.col.xml
> create mode 100644 server/lib/cimi/data/collections/machineAdmin.col.xml
> create mode 100644 server/lib/cimi/data/collections/machineConfig.col.xml
> create mode 100644 server/lib/cimi/data/collections/machineConfiguration.col.xml
> create mode 100644 server/lib/cimi/data/collections/machineImage.col.xml
> create mode 100644 server/lib/cimi/data/collections/machineTemplate.col.xml
> create mode 100644 server/lib/cimi/data/collections/meter.col.xml
> create mode 100644 server/lib/cimi/data/collections/meterTemplate.col.xml
> create mode 100644 server/lib/cimi/data/collections/network.col.xml
> create mode 100644 server/lib/cimi/data/collections/networkConfig.col.xml
> create mode 100644 server/lib/cimi/data/collections/networkTemplate.col.xml
> create mode 100644 server/lib/cimi/data/collections/system.col.xml
> create mode 100644 server/lib/cimi/data/collections/systemTemplate.col.xml
> create mode 100644 server/lib/cimi/data/collections/volume.col.xml
> create mode 100644 server/lib/cimi/data/collections/volumeConfiguration.col.xml
> create mode 100644 server/lib/cimi/data/collections/volumeImage.col.xml
> create mode 100644 server/lib/cimi/data/collections/volumeTemplate.col.xml
> create mode 100644 server/lib/cimi/data/collections/vsp.col.xml
> create mode 100644 server/lib/cimi/data/collections/vspConfig.col.xml
> create mode 100644 server/lib/cimi/data/collections/vspTemplate.col.xml
> create mode 100644 server/lib/cimi/data/defaultRes/machineAdmin.col.xml
> create mode 100644 server/lib/cimi/data/defaultRes/machineConfiguration.col.xml
> create mode 100644 server/lib/cimi/data/defaultRes/machineTemplate.col.xml
> create mode 100644 server/lib/cimi/data/defaultRes/system.col.xml
> create mode 100644 server/lib/cimi/data/defaultRes/systemTemplate.col.xml
> create mode 100644 server/lib/cimi/data/defaultRes/volumeConfiguration.col.xml
> create mode 100644 server/lib/cimi/helpers/cmwgapp_helper.rb
> create mode 100644 server/lib/cimi/helpers/cmwgres_helper.rb
> create mode 100644 server/lib/cimi/helpers/dmtfdep.rb
> create mode 100644 server/lib/cimi/server.rb
> create mode 100644 server/lib/deltacloud/server.rb
> create mode 100644 server/public/images/bread-bg.png
> create mode 100644 server/public/images/logo-wide.png
> create mode 100644 server/public/images/topbar-bg.png
> create mode 100644 server/public/javascripts/cmwgapp.js
> create mode 100644 server/public/javascripts/jquery-1.4.2.min.js
> delete mode 100644 server/server.rb
> create mode 100644 server/views/cimi/cloudEntryPoint/index.html.haml
> create mode 100644 server/views/cimi/cloudEntryPoint/index.xml.haml
> create mode 100644 server/views/cimi/collection/index.html.haml
> create mode 100644 server/views/cimi/collection/response.xml.haml
> create mode 100644 server/views/cimi/error.html.haml
> create mode 100644 server/views/cimi/errors/400.html.haml
> create mode 100644 server/views/cimi/errors/400.xml.haml
> create mode 100644 server/views/cimi/errors/401.html.haml
> create mode 100644 server/views/cimi/errors/401.xml.haml
> create mode 100644 server/views/cimi/errors/403.html.haml
> create mode 100644 server/views/cimi/errors/403.xml.haml
> create mode 100644 server/views/cimi/errors/404.html.haml
> create mode 100644 server/views/cimi/errors/404.xml.haml
> create mode 100644 server/views/cimi/errors/405.html.haml
> create mode 100644 server/views/cimi/errors/405.xml.haml
> create mode 100644 server/views/cimi/errors/500.html.haml
> create mode 100644 server/views/cimi/errors/500.xml.haml
> create mode 100644 server/views/cimi/errors/502.html.haml
> create mode 100644 server/views/cimi/errors/502.xml.haml
> create mode 100644 server/views/cimi/errors/backend_capability_failure.html.haml
> create mode 100644 server/views/cimi/layout.html.haml
> create mode 100644 server/views/cimi/machine/index.html.haml
> create mode 100644 server/views/cimi/machine/index.json.haml
> create mode 100644 server/views/cimi/machine/index.xml.haml
> create mode 100644 server/views/cimi/machine/instanceToImage.html.haml
> create mode 100644 server/views/cimi/machine/new.html.haml
> create mode 100644 server/views/cimi/machine/operation.html.haml
> create mode 100644 server/views/cimi/machine/operation.json.haml
> create mode 100644 server/views/cimi/machine/operation.xml.haml
> create mode 100644 server/views/cimi/machine/show.html.haml
> create mode 100644 server/views/cimi/machine/show.json.haml
> create mode 100644 server/views/cimi/machine/show.xml.haml
> create mode 100644 server/views/cimi/machineAdmin/new.html.haml
> create mode 100644 server/views/cimi/machineAdmin/show.html.haml
> create mode 100644 server/views/cimi/machineConfiguration/new.html.haml
> create mode 100644 server/views/cimi/machineConfiguration/show.html.haml
> create mode 100644 server/views/cimi/machineConfiguration/show.xml.haml
> create mode 100644 server/views/cimi/machineImage/index.html.haml
> create mode 100644 server/views/cimi/machineImage/index.json.haml
> create mode 100644 server/views/cimi/machineImage/index.xml.haml
> create mode 100644 server/views/cimi/machineImage/show.html.haml
> create mode 100644 server/views/cimi/machineImage/show.json.haml
> create mode 100644 server/views/cimi/machineImage/show.xml.haml
> create mode 100644 server/views/cimi/machineTemplate/new.html.haml
> create mode 100644 server/views/cimi/machineTemplate/show.html.haml
> create mode 100644 server/views/cimi/system/new.html.haml
> create mode 100644 server/views/cimi/system/show.html.haml
> create mode 100644 server/views/cimi/system/show.xml.haml
> create mode 100644 server/views/cimi/systemTemplate/new.html.haml
> create mode 100644 server/views/cimi/systemTemplate/show.html.haml
> create mode 100644 server/views/cimi/test/index.haml
> create mode 100644 server/views/cimi/test/index.html.haml
> create mode 100644 server/views/cimi/volumeConfiguration/new.html.haml
> create mode 100644 server/views/cimi/volumeConfiguration/show.html.haml
> 
> diff --git a/.gitignore b/.gitignore
> index 1ee84da..c9c0afc 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -1 +1,2 @@
> *.sw*
> +*.project
> diff --git a/server/bin/deltacloudd b/server/bin/deltacloudd
> index 166fca3..f469a36 100755
> --- a/server/bin/deltacloudd
> +++ b/server/bin/deltacloudd
> @@ -57,6 +57,9 @@ BANNER
>   opts.on( '-P', '--provider PROVIDER', 'Use PROVIDER (default is set in the driver)') do |provider|
>     ENV['API_PROVIDER'] = provider
>   end
> +  opts.on('--cimi', 'USe the DMTF CIMI frontend, not the Deltacloud frontend') do
> +    ENV['API_FRONTEND'] = 'cimi'
> +  end
>   opts.on( '-c', '--config [FILE]', 'Read provider and other config from FILE (default: ~/.deltacloud/config)') do |config|
>     options[:config] = File::expand_path(config || DEFAULT_CONFIG)
>   end
> diff --git a/server/config.ru b/server/config.ru
> index 08a7ae2..e3eb817 100644
> --- a/server/config.ru
> +++ b/server/config.ru
> @@ -16,10 +16,12 @@
> 
> require 'rubygems'
> 
> -top_srcdir = File.dirname(__FILE__)
> +$top_srcdir = File.dirname(__FILE__)
> 
> -$:.unshift File.join(top_srcdir, 'lib')
> +$:.unshift File.join($top_srcdir, 'lib')
> 
> -load File.join(top_srcdir, 'server.rb')
> +server_dir = ENV['API_FRONTEND'] == 'cimi' ? 'cimi' : 'deltacloud'
> +
> +load File.join($top_srcdir, 'lib', server_dir, 'server.rb')
> 
> run Sinatra::Application
> diff --git a/server/lib/cimi/data/collections/event.col.xml b/server/lib/cimi/data/collections/event.col.xml
> new file mode 100644
> index 0000000..fcef425
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/event.col.xml
> @@ -0,0 +1,10 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<EventCollection xmlns="http://www.dmtf.org/cimi">
> +  <uri>event</uri>
> +  <name>event collection </name>
> +  <description> The event collection </description>
> +  <created>2011-09-12 11:37:28 UTC</created>
> +  <property name="creator" type1="c" content="Tong Li" />
> +  <property name="dayOfYear" content="56" />
> +  <operation rel="edit" href="/collection/event"/>
> +</EventCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/eventLog.col.xml b/server/lib/cimi/data/collections/eventLog.col.xml
> new file mode 100644
> index 0000000..0c77ee4
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/eventLog.col.xml
> @@ -0,0 +1,10 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<EventLogCollection xmlns="http://www.dmtf.org/cimi">
> +  <uri>eventLog</uri>
> +  <name>Event log collection </name>
> +  <description> The event log collection </description>
> +  <created>2011-09-12 11:37:28 UTC</created>
> +  <property name="creator" type1="c" content="Tong Li" />
> +  <property name="dayOfYear" content="56" />
> +  <operation rel="edit" href="/collection/eventLog"/>
> +</EventLogCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/job.col.xml b/server/lib/cimi/data/collections/job.col.xml
> new file mode 100644
> index 0000000..abef1ff
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/job.col.xml
> @@ -0,0 +1,10 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<JobCollection xmlns='http://www.dmtf.org/cimi'>
> +	<uri>job</uri>
> +	<name>Job collection </name>
> +	<description>The job collection</description>
> +	<created>2011-09-12 11:37:28 UTC</created>
> +	<property name='creator' content='Tong Li' />
> +	<property name='file location' content='http://aaa.ibm.com' />
> +	<operation rel='edit' href='/collection/eventLog' />
> +</JobCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/machine.col.xml b/server/lib/cimi/data/collections/machine.col.xml
> new file mode 100644
> index 0000000..9b37310
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/machine.col.xml
> @@ -0,0 +1,11 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<MachineCollection xmlns="http://www.dmtf.org/cimi">
> +  <uri>machine</uri>
> +  <name>Machine collection </name>
> +  <description> The machine collection </description>
> +  <created>2011-09-12 11:37:28 UTC</created>
> +  <property name="creator" type1="c" content="Tong Li" />
> +  <property name="dayOfYear" content="56" />
> +  <operation rel="add" href="/machine"/>
> +  <operation rel="edit" href="/collection/machine"/>
> +</MachineCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/machineAdmin.col.xml b/server/lib/cimi/data/collections/machineAdmin.col.xml
> new file mode 100644
> index 0000000..299e840
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/machineAdmin.col.xml
> @@ -0,0 +1,11 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<MachineAdminCollection xmlns='http://www.dmtf.org/cimi'>
> +	<uri>machineAdmin</uri>
> +	<name>Machine admin collection </name>
> +	<description>The machine admin what a pity!</description>
> +	<created>2011-09-12 11:37:28 UTC</created>
> +	<property name='creator' content='Tong Li' />
> +	<property name='dayOfYear' content='56' />
> +    <operation rel="add" href="/machineAdmin"/>
> +    <operation rel="edit" href="/collection/machineAdmin"/>
> +</MachineAdminCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/machineConfig.col.xml b/server/lib/cimi/data/collections/machineConfig.col.xml
> new file mode 100644
> index 0000000..d7a7184
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/machineConfig.col.xml
> @@ -0,0 +1 @@
> +<?xml version='1.0' encoding='utf-8' ?><MachineConfigCollection xmlns='http://www.dmtf.org/cimi'><uri>machineConfig</uri><name>Machine Config collection </name><description>That is what I have changed.</description><created>2011-09-12 11:37:28 UTC</created><property name='machineCgfPrp'>propValue</property></MachineConfigCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/machineConfiguration.col.xml b/server/lib/cimi/data/collections/machineConfiguration.col.xml
> new file mode 100644
> index 0000000..0a2786f
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/machineConfiguration.col.xml
> @@ -0,0 +1,12 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<MachineConfigurationCollection xmlns='http://www.dmtf.org/cimi'>
> +	<uri>machineConfiguration</uri>
> +	<name>Machine Configuration collection </name>
> +	<description>That is jsut a test</description>
> +	<created>2011-09-12 11:37:28 UTC</created>
> +	<property name='machineCgfPrp'>propValue</property>
> +	<property name='new property'>test</property>
> +	<property name='tytyty'>0513</property>
> +    <operation rel="add" href="/machineConfiguration"/>
> +    <operation rel="edit" href="/collection/machineConfiguration"/>
> +</MachineConfigurationCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/machineImage.col.xml b/server/lib/cimi/data/collections/machineImage.col.xml
> new file mode 100644
> index 0000000..3942cf3
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/machineImage.col.xml
> @@ -0,0 +1,11 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<MachineImageCollection xmlns="http://www.dmtf.org/cimi">
> +  <uri>machineImage</uri>
> +  <name>Machine Config collection </name>
> +  <description> The machine config collection </description>
> +  <created>2011-09-12 11:37:28 UTC</created>
> +  <property name="creator" type1="c" content="Tong Li" />
> +  <property name="targetPlanet" content="earth" />
> +  <operation rel="add" href="/machineImage"/>
> +  <operation rel="edit" href="/collection/machineImage"/>
> +</MachineImageCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/machineTemplate.col.xml b/server/lib/cimi/data/collections/machineTemplate.col.xml
> new file mode 100644
> index 0000000..8cc5474
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/machineTemplate.col.xml
> @@ -0,0 +1 @@
> +<?xml version='1.0' encoding='utf-8' ?><MachineTemplateCollection xmlns='http://www.dmtf.org/cimi'><uri>machineTemplate</uri><name>Machine template collection </name><description>The machine template collection</description><created>2011-09-12 11:37:28 UTC</created><property name='machinetmp prop1'>the value</property></MachineTemplateCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/meter.col.xml b/server/lib/cimi/data/collections/meter.col.xml
> new file mode 100644
> index 0000000..4195b6c
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/meter.col.xml
> @@ -0,0 +1,11 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<MeterCollection xmlns="http://www.dmtf.org/cimi">
> +  <uri>meter</uri>
> +  <name>Meter collection </name>
> +  <description> The meter collection </description>
> +  <created>2011-09-12 11:37:28 UTC</created>
> +  <property name="creator" type1="c" content="Tong Li" />
> +  <property name="dayOfYear" content="56" />
> +  <operation rel="add" href="/meter"/>
> +  <operation rel="edit" href="/collection/meter"/>
> +</MeterCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/meterTemplate.col.xml b/server/lib/cimi/data/collections/meterTemplate.col.xml
> new file mode 100644
> index 0000000..4d146fb
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/meterTemplate.col.xml
> @@ -0,0 +1,11 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<MeterTemplateCollection xmlns='http://www.dmtf.org/cimi'>
> +	<uri>meterTemplate</uri>
> +	<name>Meter template collection </name>
> +	<description>The meter template collection</description>
> +	<created>2011-09-12 11:37:28 UTC</created>
> +	<property name='creator'>Tong Li</property>
> +	<property name='dayOfYear'>56</property>
> +	<operation rel='add' href='/meterTemplate' />
> +	<operation rel='edit' href='/collection/meterTemplate' />
> +</MeterTemplateCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/network.col.xml b/server/lib/cimi/data/collections/network.col.xml
> new file mode 100644
> index 0000000..f5b845b
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/network.col.xml
> @@ -0,0 +1,11 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<NetworkCollection xmlns="http://www.dmtf.org/cimi">
> +  <uri>network</uri>
> +  <name>Network collection </name>
> +  <description> The network config collection </description>
> +  <created>2011-09-12 11:37:28 UTC</created>
> +  <property name="creator" type1="c" content="Tong Li" />
> +  <property name="dayOfYear" content="56" />
> +  <operation rel="add" href="/network"/>
> +  <operation rel="edit" href="/collection/network"/>
> +</NetworkCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/networkConfig.col.xml b/server/lib/cimi/data/collections/networkConfig.col.xml
> new file mode 100644
> index 0000000..9fb5ecb
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/networkConfig.col.xml
> @@ -0,0 +1,11 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<NetworkConfigCollection xmlns="http://www.dmtf.org/cimi">
> +  <uri>networkConfig</uri>
> +  <name>Network config collection </name>
> +  <description> The network config collection </description>
> +  <created>2011-09-12 11:37:28 UTC</created>
> +  <property name="creator" type1="c" content="Tong Li" />
> +  <property name="dayOfYear" content="56" />
> +  <operation rel="add" href="/networkConfig"/>
> +  <operation rel="edit" href="/collection/networkConfig"/>
> +</NetworkConfigCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/networkTemplate.col.xml b/server/lib/cimi/data/collections/networkTemplate.col.xml
> new file mode 100644
> index 0000000..744f07c
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/networkTemplate.col.xml
> @@ -0,0 +1,11 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<NetworkTemplateCollection xmlns="http://www.dmtf.org/cimi">
> +  <uri>networkTemplate</uri>
> +  <name>Network template collection </name>
> +  <description> The network template collection </description>
> +  <created>2011-09-12 11:37:28 UTC</created>
> +  <property name="creator" type1="c" content="Tong Li" />
> +  <property name="dayOfYear" content="56" />
> +  <operation rel="add" href="/networkTemplate"/>
> +  <operation rel="edit" href="/collection/networkTemplate"/>
> +</NetworkTemplateCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/system.col.xml b/server/lib/cimi/data/collections/system.col.xml
> new file mode 100644
> index 0000000..7df3a7f
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/system.col.xml
> @@ -0,0 +1 @@
> +<?xml version='1.0' encoding='utf-8' ?><SystemCollection xmlns='http://www.dmtf.org/cimi'><uri>system</uri><name>system collection </name><description>the system collection change 01</description><created>2011-09-12 11:37:28 UTC</created><property name='creator'>Tong Li</property><property name='systemCollectionProp'>whhhooo</property></SystemCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/systemTemplate.col.xml b/server/lib/cimi/data/collections/systemTemplate.col.xml
> new file mode 100644
> index 0000000..060ee98
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/systemTemplate.col.xml
> @@ -0,0 +1,6 @@
> +<?xml version='1.0' encoding='utf-8' ?><SystemTemplateCollection xmlns='http://www.dmtf.org/cimi'><uri>systemTemplate</uri>
> +<name>system template collection asas</name>
> +<description>the system templatyytyuyuuhghjg</description>
> +<created>2011-09-12 11:37:28 UTC</created>
> +<property name='World creator'>God</property>
> +</SystemTemplateCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/volume.col.xml b/server/lib/cimi/data/collections/volume.col.xml
> new file mode 100644
> index 0000000..279df45
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/volume.col.xml
> @@ -0,0 +1,11 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<VolumeCollection xmlns="http://www.dmtf.org/cimi">
> +  <uri>volume</uri>
> +  <name>Volume collection </name>
> +  <description> The volume collection </description>
> +  <created>2011-09-12 11:37:28 UTC</created>
> +  <property name="creator" type1="c" content="Tong Li" />
> +  <property name="dayOfYear" content="56" />
> +  <operation rel="add" href="/volume"/>
> +  <operation rel="edit" href="/collection/volume"/>
> +</VolumeCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/volumeConfiguration.col.xml b/server/lib/cimi/data/collections/volumeConfiguration.col.xml
> new file mode 100644
> index 0000000..3e1827e
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/volumeConfiguration.col.xml
> @@ -0,0 +1 @@
> +<?xml version='1.0' encoding='utf-8' ?><VolumeConfigurationCollection xmlns='http://www.dmtf.org/cimi'><uri>volumeConfiguration</uri><name>Volume configuration collection </name><description>The volume config</description><created>2011-09-12 11:37:28 UTC</created><property name='creator'>Tong Li</property></VolumeConfigurationCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/volumeImage.col.xml b/server/lib/cimi/data/collections/volumeImage.col.xml
> new file mode 100644
> index 0000000..2b34452
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/volumeImage.col.xml
> @@ -0,0 +1,11 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<VolumeImageCollection xmlns="http://www.dmtf.org/cimi">
> +  <uri>volumeImage</uri>
> +  <name>Volume image collection </name>
> +  <description> The volume image collection </description>
> +  <created>2011-09-12 11:37:28 UTC</created>
> +  <property name="creator" type1="c" content="Tong Li" />
> +  <property name="dayOfYear" content="56" />
> +  <operation rel="add" href="/volumeImage"/>
> +  <operation rel="edit" href="/collection/volumeImage"/>
> +</VolumeImageCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/volumeTemplate.col.xml b/server/lib/cimi/data/collections/volumeTemplate.col.xml
> new file mode 100644
> index 0000000..461aab7
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/volumeTemplate.col.xml
> @@ -0,0 +1 @@
> +<?xml version='1.0' encoding='utf-8' ?><VolumeTemplateCollection xmlns='http://www.dmtf.org/cimi'><uri>volumeTemplate</uri><name>Volume template collection </name><description>The volume template collection</description><created>2011-09-12 11:37:28 UTC</created><property name='creator'>Tong Li</property><property name='dayOfYear'>56</property></VolumeTemplateCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/vsp.col.xml b/server/lib/cimi/data/collections/vsp.col.xml
> new file mode 100644
> index 0000000..cf6830d
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/vsp.col.xml
> @@ -0,0 +1,11 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<VspCollection xmlns="http://www.dmtf.org/cimi">
> +  <uri>vspConfig</uri>
> +  <name>Vsp collection </name>
> +  <description> The vsp collection </description>
> +  <created>2011-09-12 11:37:28 UTC</created>
> +  <property name="creator" type1="c" content="Tong Li" />
> +  <property name="dayOfYear" content="56" />
> +  <operation rel="add" href="/vsp"/>
> +  <operation rel="edit" href="/collection/vsp"/>
> +</VspCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/vspConfig.col.xml b/server/lib/cimi/data/collections/vspConfig.col.xml
> new file mode 100644
> index 0000000..9a476d9
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/vspConfig.col.xml
> @@ -0,0 +1,11 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<VspConfigCollection xmlns="http://www.dmtf.org/cimi">
> +  <uri>vspConfig</uri>
> +  <name>Vsp config collection </name>
> +  <description> The vsp config collection </description>
> +  <created>2011-09-12 11:37:28 UTC</created>
> +  <property name="creator" type1="c" content="Tong Li" />
> +  <property name="dayOfYear" content="56" />
> +  <operation rel="add" href="/vspConfig"/>
> +  <operation rel="edit" href="/collection/vspConfig"/>
> +</VspConfigCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/collections/vspTemplate.col.xml b/server/lib/cimi/data/collections/vspTemplate.col.xml
> new file mode 100644
> index 0000000..0f1b812
> --- /dev/null
> +++ b/server/lib/cimi/data/collections/vspTemplate.col.xml
> @@ -0,0 +1 @@
> +<?xml version='1.0' encoding='utf-8' ?><VspTemplateCollection xmlns='http://www.dmtf.org/cimi'><uri>vspTemplate</uri><name>Vsp template collection </name><description>The vsp template collection</description><created>2011-09-12 11:37:28 UTC</created><property name='creator' content='Tong Li' /><property name='dayOfYear' content='56' /><property name='qqqqq' content='' /></VspTemplateCollection>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/defaultRes/machineAdmin.col.xml b/server/lib/cimi/data/defaultRes/machineAdmin.col.xml
> new file mode 100644
> index 0000000..a507f80
> --- /dev/null
> +++ b/server/lib/cimi/data/defaultRes/machineAdmin.col.xml
> @@ -0,0 +1,11 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<MachineAdmin xmlns="http://www.dmtf.org/cimi">
> +  <uri>machineAdmin</uri>
> +  <name>Default machine admin name </name>
> +  <description>Default machine admin description</description>
> +  <created>2011-01-01 11:37:28 UTC</created>
> +  <property name="username" content="tongli@creators.com" />
> +  <property name="password" content="secret" />
> +  <operation rel="edit" href="/machineAdmin"/>
> +  <operation rel="delete" href="/machineAdmin"/>
> +</MachineAdmin>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/defaultRes/machineConfiguration.col.xml b/server/lib/cimi/data/defaultRes/machineConfiguration.col.xml
> new file mode 100644
> index 0000000..037fd88
> --- /dev/null
> +++ b/server/lib/cimi/data/defaultRes/machineConfiguration.col.xml
> @@ -0,0 +1,17 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<MachineConfiguration xmlns="http://www.dmtf.org/cimi">
> +  <uri>machineConfiguration</uri>
> +  <name>Default machine configuration name </name>
> +  <description>Default machine onfiguration description</description>
> +  <created>2011-01-01 00:00:01 UTC</created>
> +  <cpu>ext4</cpu>
> +  <memory quantity="10" units="gigabyte" />
> +  <disk>
> +  	<capacity quantity="200" units="gigabyte"/>
> +  	<guestInterface>SATA</guestInterface>
> +  </disk>
> +  <supportsSnapshots>false</supportsSnapshots>
> +  <guestInterface>http://www.ibm.com</guestInterface>
> +  <operation rel="edit" href="/machineConfiguration"/>
> +  <operation rel="delete" href="/machinieConfiguration"/>
> +</MachineConfiguration>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/defaultRes/machineTemplate.col.xml b/server/lib/cimi/data/defaultRes/machineTemplate.col.xml
> new file mode 100644
> index 0000000..feaffec
> --- /dev/null
> +++ b/server/lib/cimi/data/defaultRes/machineTemplate.col.xml
> @@ -0,0 +1,12 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<MachineTemplate xmlns="http://www.dmtf.org/cimi">
> +  <uri>machineTemplate</uri>
> +  <name>Default machine template name </name>
> +  <description>Default machine template description</description>
> +  <created>2011-01-01 00:00:01 UTC</created>
> +  <property name="prop1" content="prop1 value" />
> +  <machineConfig href="machineConfig_id" />
> +  <machineImage href="machineImage_id" />
> +  <operation rel="edit" href="/machineTemplate"/>
> +  <operation rel="delete" href="/machineTemplate"/>
> +</MachineTemplate>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/defaultRes/system.col.xml b/server/lib/cimi/data/defaultRes/system.col.xml
> new file mode 100644
> index 0000000..d3c7a1a
> --- /dev/null
> +++ b/server/lib/cimi/data/defaultRes/system.col.xml
> @@ -0,0 +1,12 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<System xmlns="http://www.dmtf.org/cimi">
> +  <uri>system</uri>
> +  <name>Default system name </name>
> +  <description>Default system description</description>
> +  <created>2011-01-01 00:00:01 UTC</created>
> +  <property name="prop1" content="prop value" />
> +  <state>INITIATED</state>
> +  <status>STOPPED</status>
> +  <operation rel="edit" href="/system"/>
> +  <operation rel="delete" href="/system"/>
> +</System>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/defaultRes/systemTemplate.col.xml b/server/lib/cimi/data/defaultRes/systemTemplate.col.xml
> new file mode 100644
> index 0000000..0f6be07
> --- /dev/null
> +++ b/server/lib/cimi/data/defaultRes/systemTemplate.col.xml
> @@ -0,0 +1,10 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<SystemTemplate xmlns="http://www.dmtf.org/cimi">
> +  <uri>systemTemplate</uri>
> +  <name>Default system template name </name>
> +  <description>Default system template description</description>
> +  <created>2011-01-01 00:00:01 UTC</created>
> +  <property name="username" content="tongli@creators.com" />
> +  <operation rel="edit" href="/systemTemplate"/>
> +  <operation rel="delete" href="/systemTemplate"/>
> +</SystemTemplate>
> \ No newline at end of file
> diff --git a/server/lib/cimi/data/defaultRes/volumeConfiguration.col.xml b/server/lib/cimi/data/defaultRes/volumeConfiguration.col.xml
> new file mode 100644
> index 0000000..97d240c
> --- /dev/null
> +++ b/server/lib/cimi/data/defaultRes/volumeConfiguration.col.xml
> @@ -0,0 +1,14 @@
> +<?xml version='1.0' encoding='utf-8' ?>
> +<VolumeConfiguration xmlns="http://www.dmtf.org/cimi">
> +  <uri>volumeConfiguration</uri>
> +  <name>Default volume configuration name </name>
> +  <description>Default volume configuration description</description>
> +  <created>2011-01-01 00:00:01 UTC</created>
> +  <property name="username" content="tongli@creators.com" />
> +  <format>ext4</format>
> +  <capacity quantity="200" units="gigabyte"/>
> +  <supportsSnapshots> xs:boolean </supportsSnapshots>
> +  <guestInterface>http://www.ibm.com</guestInterface>
> +  <operation rel="edit" href="/volumeConfiguration"/>
> +  <operation rel="delete" href="/volumeConfiguration"/>
> +</VolumeConfiguration>
> \ No newline at end of file
> diff --git a/server/lib/cimi/helpers/cmwgapp_helper.rb b/server/lib/cimi/helpers/cmwgapp_helper.rb
> new file mode 100644
> index 0000000..5e16eb8
> --- /dev/null
> +++ b/server/lib/cimi/helpers/cmwgapp_helper.rb
> @@ -0,0 +1,352 @@
> +# Licensed to the Apache Software Foundation (ASF) under one or more
> +# contributor license agreements.  See the NOTICE file distributed with
> +# this work for additional information regarding copyright ownership.  The
> +# ASF licenses this file to you under the Apache License, Version 2.0 (the
> +# "License"); you may not use this file except in compliance with the
> +# License.  You may obtain a copy of the License at
> +#
> +#       http://www.apache.org/licenses/LICENSE-2.0
> +#
> +# Unless required by applicable law or agreed to in writing, software
> +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
> +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
> +# License for the specific language governing permissions and limitations
> +# under the License.
> +
> +# Methods added to this helper will be available to all templates in the application.
> +
> +require 'benchmark'
> +
> +# this section defines constants used in the implementation.
> +
> +CMPAPIS = [:cloudEntryPoint, :systemTemplate, :system, :machineTemplate, :machineConfiguration, :machineImage, :machineAdmin,
> +       :machine, :volumeTemplate, :volumeConfiguration, :volumeImage, :volume, :networkTemplate, :networkConfig, :network,
> +       :vspTemplate, :vspConfig, :vsp, :meterTemplate, :meter, :eventLog, :event, :job ]
> +
> +aRESOURCENAMES = ""
> +CMPAPIS.map { |item| aRESOURCENAMES += item.to_s + "," unless item == :cloudEntryPoint}
> +
> +RESOURCENAMES = aRESOURCENAMES
> +
> +SUPPORTEDRES = :machineConfiguration.to_s + "," + :machineImage.to_s + "," + :machine.to_s + "," + 
> +               :volume.to_s
> +
> +
> +HOST_API_PATH="http://#{ENV["API_HOST"]}:#{ENV["API_PORT"]}/api"
> +CMWG_NAMESPACE = "http://www.dmtf.org/cimi"
> +XS_NAMESPACE = "http://www.w3.org/2001/XMLSchema"
> +HEADER_API_VERSION = "1.0"
> +HEADER_CIMI_SPECIFICATION_VERSION = "X-CIMI-Specification-Version" + " :" + HEADER_API_VERSION
> +
> +def fixupContent(aHash, keyName="content", attrName="name")
> +  if aHash

The 'if aHash' can be safely avoided here.

> +    aHash.each_pair do |key, value|

aHash.each_pair do |key, value| can be replaced with just aHash.each do |key, value|

> +      if value.kind_of? (Hash)

In Ruby, you don't need to use () here, just 'if value.kind_of? Hash' is usually enough.

>        
> +        #We can only handle the element without any other attribute, 
> +        #if the element also has other attribute, then we can not do fixups since it will lose information.
> +        if value[keyName] && value.size == 1
> +          aHash[key] = value[keyName]
> +        elsif value[keyName] && value[attrName] && value.size == 2
> +          aHash[key] = { "#{value[attrName]}" => value[keyName] }
> +        else
> +          fixupContent value, keyName, attrName
> +        end
> +      end
> +    end
> +  end
> +end
> +
> +def isValid(anObj)

In Ruby, you usually use is_valid? instead of isValid(). As result, the code will be more readable for
other developers.

> +  if anObj == nil then return false end

then .. end can be safely avoided by:

return false unless anObj

> +  if anObj["uri"].nil? || anObj["name"].nil? || anObj["created"].nil? then return false end
> +  true
> +end   
> +
> +module ApplicationHelper
> +
> +  include Deltacloud
> +
> +  def bread_crumb_ext
> +    s = "<ul class='breadcrumb'><li class='first'><a href='#{root_url}'>&#948 home</a></li>"
> +    s+="<li class='docs'>#{link_to_documentation}</li>"
> +    s+="</ul>"
> +  end
> +
> +  def machine_action(name)
> +    original_instance = driver.instance(credentials, :id => params[:id])
> +
> +    @operationParam = { "machineId" => params[:id], "machineOperation" => name}
> +
> +    # If original instance doesn't include called action
> +    # return with 405 error (Method is not Allowed)
> +    if original_instance 
> +      unless driver.instance_actions_for(original_instance.state).include?(name.to_sym)
> +        return report_error(405, 'not_allowed')
> +      end
> +    end
> +
> +    @instance = driver.send(:"#{name}_instance", credentials, params["id"])
> +
> +    respond_to do |format|
> +      puts "the format is " + format.to_s
> +      format.html { haml :"machine/operation" }
> +      format.xml  { haml :"machine/operation" }
> +      format.json do            
> +        responseXML = haml :"machine/operation"
> +        res = Hash.from_xml(responseXML).to_json
> +        res 

You don't need to use 'res' variable here, Hash.from_xml(responseXML).to_json will
return JSON already.


> +      end        
> +    end            
> +  end
> +
> +  def link_to_action_ext(action, url, method, params)
> +    capture_haml do
> +      haml_tag :form, :method => method.to_sym, :action => url, :class => [:link, method] do
> +        params.each do |key, value|           
> +          haml_tag :input, :type => :hidden, :name => key, :value => value
> +        end
> +        haml_tag :button, :type => :button, :onClick => "return do#{method.capitalize}(this)" do 
> +          haml_concat action
> +        end
> +      end
> +    end
> +  end
> +
> +  def getCollectionItem(collType)
> +    colItem = []
> +    fileList = Dir.glob File.join(STOREROOT,"*." + collType)
> +    if fileList && (fileList.empty? == false)
> +      fileList.map do |item|
> +        colfile = File.read(item)   
> +        rootHash = Hash.from_xml colfile
> +        if rootHash.first
> +          if rootHash.first[1]

These 'if-s' can be collapsed to:

if rootHash.first and rootHash.first[1]

> +            newItem = {
> +              "name" => rootHash.first[1]["name"],
> +              "href" => HOST_API_PATH + "/" + collType + "/" + rootHash.first[1]["uri"]
> +            }
> +            colItem.insert 0,  newItem
> +          end
> +        end        
> +      end
> +    end
> +    puts colItem.inspect

^^ Looks like you have forgotten some debugging stuff here ;-)

> +    colItem
> +  end
> +
> +  def getCollectionItemFromDC(collType)
> +    colItem = []
> +    case collType
> +    when "machineConfiguration"
> +      profiles = driver.hardware_profiles(credentials, nil)
> +      if profiles
> +        profiles.map do |profile|
> +          newItem = {
> +             "name" => profile.name,
> +             "uri" => profile.name,
> +             "href" => HOST_API_PATH + "/" + collType + "/" + profile.name
> +          }
> +          
> +          profile.each_property do |p|
> +            newItem["#{p.name}"] = { "content" => p.value, "units" => p.unit}
> +          end
> +          
> +          colItem.insert 0,  newItem
> +        end
> +      end
> +    when "machineImage"
> +      #Retrieve machine images
> +      images = driver.send(:images, credentials, {})
> +      if images
> +        images.map do |image|
> +          newItem = {
> +             "name" => image.name,
> +             "description" => image.description,
> +             "state" => image.state,
> +             "architecture" => image.architecture,
> +             "uri" => image.id,
> +             "href" => HOST_API_PATH + "/" + collType + "/" + image.id
> +          }
> +          colItem.insert 0,  newItem
> +        end
> +      end
> +    when "machine"
> +      #Retrieve instances
> +      instances = driver.send(:instances, credentials, {})
> +      if instances
> +        instances.map do |instance|
> +          newItem = {
> +             "name" => instance.name,
> +             "href" => HOST_API_PATH + "/" + collType + "/" + instance.id
> +          }
> +          colItem.insert 0,  newItem
> +        end
> +      end
> +    when "volume"
> +      instances = driver.send(:storage_volumes, credentials, {})
> +      if instances
> +        instances.map do |instance|
> +          puts instance.inspect
> +          newItem = {
> +             "name" => instance.id,
> +             "href" => HOST_API_PATH + "/" + collType + "/" + instance.id
> +          }
> +          colItem.insert 0,  newItem
> +        end
> +      end      
> +    end
> +    colItem
> +  end
> +   
> +  def getResponseContentType(collType, format="html") 
> +    if format == "text/html"
> +      acceptFormat = ""
> +    elsif format == "xml"
> +      acceptFormat = "application/CIMI-" + collType + "+xml"
> +    elsif format == "json"
> +      acceptFormat = "application/CIMI-" + collType + "+json"
> +    end

^^
It would be nice to replace this piece of code with 'case' and 'when'

> +    acceptFormat 
> +    #if acceptFormat.include?("application") && acceptFormat.include?()
> +    #"application/CIMI-" + collType + "+" + format
> +  end
> +   
> +  def handlePost
> +    raw = request.env["rack.input"].read
> +    
> +    rootHash = Hash.from_xml raw
> +    
> +    @xmlRootNode = rootHash.first[0]
> +    @dmtfitem = rootHash.first[1]
> +    puts @xmlRootNode.inspect
> +    fileId = @dmtfitem["uri"]
> +    puts @dmtfitem["uri"].inspect

^^ Another debugging orphan ;)

> +        
> +    filePath = File.join(STOREROOT, fileId + '.' + params[:collType])   
> +    if isValid(@dmtfitem) && File.exist?(filePath) == false

As I mentioned before, here you can see a nice example why to rename 'isValid' to 'is_valid?'

>  
> +      aFile = File.new(filePath, "w")
> +      aFile.write(raw)
> +      aFile.close

It's a good practice to use this syntax when writing to a file:

File.new(filePath, 'w') do |f|
  f.write(raw
end

The file will be automatically closed at the end of the block.

> +  
> +      respond_to do |format|
> +        format.xml do
> +          response.status = 201
> +          response['Location'] = HOST_API_PATH + "#{params[:collType]}/#{fileId}"
> +          haml :"collection/response"     
> +        end
> +      end
> +    else
> +      report_error(409)
> +    end         
> +  end
> +  
> +  def handleCollectionPut
> +    if RESOURCENAMES.include? params[:id]
> +                
> +      raw = request.env["rack.input"].read
> +      
> +      filePath = File.join(STOREROOT, 'collections/' + params[:id] + '.col.xml')
> +      if File.exist?(filePath)
> +        
> +        aFile = File.new(filePath, "w")
> +        aFile.write(raw)
> +        aFile.close

^^ see above.

> +      
> +        status 200
> +        respond_to do |format|
> +          format.xml  { haml :"collection/response"}        
> +        end
> +      else
> +        report_error(404)
> +      end
> +    else
> +      report_error(404)
> +    end
> +  end
> +  
> +  def handleResourcePut
> +    raw = request.env["rack.input"].read
> +    rootHash = Hash.from_xml raw
> +    
> +    @xmlRootNode = rootHash.first[0]
> +    @dmtfitem = rootHash.first[1]
> +    puts @xmlRootNode.inspect

^^ debug?
 
> +    fileId = @dmtfitem["uri"]
> +    puts @dmtfitem["uri"].inspect
> +        
> +    filePath = File.join(STOREROOT, fileId + '.' + params[:collType])
> +    #we want to check if the file exist and if the passed in id is the same as uri in the block passed in
> +    if File.exist?(filePath) && fileId == params[:id]
> +      aFile = File.new(filePath, "w")
> +      aFile.write(raw)
> +      aFile.close

^^ see above

> +    
> +      respond_to do |format|
> +        format.xml do
> +          response.status = 200
> +          response['Location'] = HOST_API_PATH + "#{params[:collType]}/#{fileId}"
> +          haml :"collection/response"     
> +        end
> +      end
> +    else
> +      report_error(404)
> +    end  
> +  end
> +  
> +  def handleResourceDelete
> +    filePath = File.join(STOREROOT, params[:id] + '.' + params[:collType])
> +    if File.exist?(filePath)
> +      colfile = File.delete(filePath)   
> +      respond_to do |format|
> +        format.xml  do 
> +          response.status = 200
> +          response['Location'] = HOST_API_PATH + "#{params[:collType]}/#{params[:id]}"
> +          haml :"collection/response"     
> +        end          
> +        format.json do            
> +          engine = Haml::Engine.new(File.read(settings.views + "/collection/response"))
> +          responseXML = engine.render self
> +          res = Hash.from_xml(responseXML).to_json
> +        end          
> +      end
> +    else
> +      report_error(404)
> +    end      
> +  end
> +  
> +  def handleResourceGet
> +    
> +    checkDCResource

Dunno the original meaning of this method but in Ruby it is a common practice to use exclamation
mark for methods which don't return anything:

I suggest to change this method to 'check_dc_resource!'

> +    filePath = File.join(STOREROOT, params[:id] + '.' + params[:collType])
> +    if File.exist?(filePath)
> +      respond_to do |format|
> +        format.html do
> +          rootHash = XmlSimple.xml_in(filePath, {'ForceArray'=>false, 'KeepRoot'=>true, 'KeyAttr'=>['name']})
> +          puts rootHash.inspect

^^ another debugging puts

> +          @xmlRootNode = rootHash.first[0]
> +          @dmtfitem = rootHash.first[1]   
> +          puts @dmtfitem

^^ see above :)

> +          pathName = params[:collType] + "/show"                          
> +          haml pathName.to_sym
> +        end
> +        format.xml do          
> +          File.read(filePath)
> +        end          
> +        format.json do            
> +          rootHash = XmlSimple.xml_in(filePath, {'ForceArray'=>false, 'KeepRoot'=>true, 'KeyAttr'=>['name']})
> +          puts rootHash.inspect
> +          jsonHash = rootHash.first[1]
> +          puts jsonHash.inspect
> +          if jsonHash.has_key?("xmlns")
> +            jsonHash.delete "xmlns"
> +          end
> +          fixupContent jsonHash
> +          res = jsonHash.to_json                  
> +        end          
> +      end
> +    else
> +      report_error(404)
> +    end      
> +  end
> +end
> diff --git a/server/lib/cimi/helpers/cmwgres_helper.rb b/server/lib/cimi/helpers/cmwgres_helper.rb
> new file mode 100644
> index 0000000..4dd717f
> --- /dev/null
> +++ b/server/lib/cimi/helpers/cmwgres_helper.rb
> @@ -0,0 +1,38 @@
> +
> +
> +module ApplicationHelper
> +
> +  def checkDCResource()

^^ see the renaming suggestion from above.

> +    
> +    if SUPPORTEDRES.include?(params[:collType])
> +      filePath = File.join(STOREROOT, params[:id] + '.' + params[:collType])
> +      allRes = getCollectionItemFromDC(params[:collType])
> +      #getting the resource that match the passed in id.
> +      aRes = allRes.select { |item| item["uri"] == params[:id]}
> +      #if the array is not empty
> +      if aRes.empty? == false
> +        #using driver as part of the file name to have some namespace. 
> +        filePath = File.join(STOREROOT, params[:id] + '.' + params[:collType] + "." + ENV["API_DRIVER"])
> +        #using default value xml
> +        defaultFilePath = File.join(STOREROOT, "defaultRes/" + params[:collType] + ".col.xml")
> +        #read the default xml file in, then mixin the retrieved value, then save it for further process.
> +        
> +        rootHash = XmlSimple.xml_in(defaultFilePath, { 'ForceArray' => false, 'KeepRoot'=>true, 'KeyAttr' => ['name']})
> +        
> +        puts "from DC"
> +        puts aRes.first
> +        
> +        newHash = rootHash.first[1].merge(aRes.first)
> +        
> +        puts "after merge"
> +        puts newHash.inspect

^^ a lot of debugging puts here.


> +        
> +      end
> +    end
> +    params[:id] + '.' + params[:collType]
> +  end
> +  
> +  def logStr(strParam)
> +    puts strParam.inspect
> +  end
> +end
> \ No newline at end of file
> diff --git a/server/lib/cimi/helpers/dmtfdep.rb b/server/lib/cimi/helpers/dmtfdep.rb
> new file mode 100644
> index 0000000..b29ec31
> --- /dev/null
> +++ b/server/lib/cimi/helpers/dmtfdep.rb
> @@ -0,0 +1,44 @@
> +require 'sinatra'
> +require 'drivers'
> +require 'deltacloud/core_ext/integer'
> +require 'deltacloud/core_ext/hash'
> +require 'deltacloud/core_ext/string'
> +require 'deltacloud/base_driver'
> +require 'deltacloud/hardware_profile'
> +require 'deltacloud/state_machine'
> +require 'deltacloud/helpers'
> +require 'deltacloud/models/base_model'
> +require 'deltacloud/models/realm'
> +require 'deltacloud/models/image'
> +require 'deltacloud/models/instance'
> +require 'deltacloud/models/key'
> +require 'deltacloud/models/address'
> +require 'deltacloud/models/instance_profile'
> +require 'deltacloud/models/storage_snapshot'
> +require 'deltacloud/models/storage_volume'
> +require 'deltacloud/models/bucket'
> +require 'deltacloud/models/blob'
> +require 'deltacloud/models/load_balancer'
> +require 'deltacloud/models/firewall'
> +require 'deltacloud/models/firewall_rule'
> +
> +require 'json'
> +require 'sinatra/rack_accept'
> +require 'sinatra/static_assets'
> +require 'sinatra/rabbit'
> +require 'sinatra/lazy_auth'
> +require 'erb'
> +require 'haml'
> +require 'open3'
> +require 'uuidtools'
> +require 'xmlsimple'
> +require 'deltacloud/helpers/blob_stream'
> +require 'sinatra/rack_driver_select'
> +require 'sinatra/rack_runtime'
> +require 'sinatra/rack_etag'
> +require 'sinatra/rack_date'
> +require 'sinatra/rack_matrix_params'
> +require 'sinatra/rack_syslog'
> +#require 'active_support/inflector'
> +#require 'active_support/core_ext/object/blank'
> +require 'active_support/core_ext/hash/conversions'
> diff --git a/server/lib/cimi/server.rb b/server/lib/cimi/server.rb
> new file mode 100644
> index 0000000..38bbcf2
> --- /dev/null
> +++ b/server/lib/cimi/server.rb
> @@ -0,0 +1,267 @@
> +# Licensed to the Apache Software Foundation (ASF) under one or more
> +# contributor license agreements.  See the NOTICE file distributed with
> +# this work for additional information regarding copyright ownership.  The
> +# ASF licenses this file to you under the Apache License, Version 2.0 (the
> +# "License"); you may not use this file except in compliance with the
> +# License.  You may obtain a copy of the License at
> +#
> +#       http://www.apache.org/licenses/LICENSE-2.0
> +#
> +# Unless required by applicable law or agreed to in writing, software
> +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
> +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
> +# License for the specific language governing permissions and limitations
> +# under the License.
> +
> +
> +require 'cimi/helpers/dmtfdep'
> +require 'cimi/helpers/cmwgres_helper'
> +require 'cimi/helpers/cmwgapp_helper'
> +
> +
> +# FIXME: Can we get rid of the dependency on active_support ?
> +#require 'active_support'
> +#require 'active_support/inflector'
> +#require 'active_support/core_ext/object/blank'
> +#require 'active_support/core_ext/hash/conversions'
> +
> +set :version, '0.1.0'
> +
> +include Deltacloud::Drivers
> +set :drivers, Proc.new { driver_config }
> +
> +# CIMI has different default collections
> +DEFAULT_COLLECTIONS = CMPAPIS
> +
> +# FIXME: This contains a mix of static and dynamically modified data. This
> +# needs to be separated out, and only drivers should touch dynamic data
> +
> +# FIXME: There used to be code that created STOREROOT when it doesn't
> +# exist.  But not having storeroot leads to an error when requesting the
> +# entry point
> +
> +# here we setup a directory for persistence, everything will be saved as
> +# files the file format will be uuid.resourceTypeName, for example: if
> +# there is a machineTemplte, and its id is
> +# dab4fdae-1451-48f4-b5b6-2b0dcc06bb14, then the file at the storage will
> +# be dab4fdae-1451-48f4-b5b6-2b0dcc06bb14.machineTemplate, each file
> +# content should be in xml format.  the root directory of the storage is
> +# <rootDir>/store so we create one if one does not exist yet.
> +
> +STOREROOT = File.join($top_srcdir, 'lib', 'cimi', 'data')
> +puts "store root is " + STOREROOT
> +
> +Sinatra::Application.register Rack::RespondTo
> +
> +use Rack::ETag
> +use Rack::Runtime
> +use Rack::MatrixParams
> +use Rack::DriverSelect
> +use Rack::MediaType
> +use Rack::Date
> +
> +configure do
> +  set :views, File::join($top_srcdir, 'views', 'cimi')
> +  set :public, File::join($top_srcdir, 'public')
> +  # Try to load the driver on startup to fail early if there are issues
> +  driver
> +  # FIXME: Reduce the places that need access to STOREROOT
> +  set :store, STOREROOT
> +end
> +
> +configure :production do
> +  use Rack::SyslogLogger
> +  disable :logging
> +  enable :show_errors
> +  set :dump_errors, false
> +  $stdout = SyslogFile.new
> +  $stderr = $stdout
> +end
> +
> +configure :development do
> +  # So we can just use puts for logging
> +  set :raise_errors => false
> +  set :show_exceptions, false
> +  $stdout.sync = true
> +  $stderr.sync = true
> +end
> +
> +# You could use $API_HOST environment variable to change your hostname to
> +# whatever you want (eg. if you running API behind NAT)
> +HOSTNAME=ENV['API_HOST'] ? ENV['API_HOST'] : nil
> +
> +error do
> +  report_error
> +end
> +
> +puts "application root URL:" + HOST_API_PATH
> +
> +get '/' do redirect root_url, 301; end
> +
> +get "#{Sinatra::UrlForHelper::DEFAULT_URI_PREFIX}\/?" do
> +  if params[:force_auth]
> +    return [401, 'Authentication failed'] unless driver.valid_credentials?(credentials)
> +  end
> +
> +  @allAPIs = CMPAPIS
> +  respond_to do |format|
> +    format.xml { haml :"cloudEntryPoint/index" }
> +    format.json do
> +      { :api => {
> +          :version => settings.version,
> +          :driver => driver_symbol,
> +          :links => entry_points.collect do |l|
> +            { :rel => l[0], :href => l[1] }.merge(json_features_for_entrypoint(l))
> +          end
> +        }
> +      }.to_json
> +    end
> +    format.html { haml :"cloudEntryPoint/index" }
> +  end
> +end
> +
> +get "/api/cloudEntryPoint" do
> +
> +  @allAPIs = CMPAPIS
> +  respond_to do |format|
> +    format.xml  do
> +      content_type 'application/CIMI-CloudEntryPoint+xml', :charset => 'utf-8'
> +      haml:"cloudEntryPoint/index" 
> +    end                
> +    format.html { haml:"cloudEntryPoint/index" }        
> +    format.json do
> +      content_type 'application/CIMI-CloudEntryPoint+json', :charset => 'utf-8'            
> +      engine = Haml::Engine.new(File.read(settings.views + "/cloudEntryPoint/index.xml.haml"))
> +      responseXML = engine.render self
> +      jsonHash = Hash.from_xml responseXML
> +      puts jsonHash.inspect
> +      jsonHash = jsonHash.first[1]
> +      puts jsonHash.inspect
> +      if jsonHash.has_key?("xmlns")
> +        jsonHash.delete "xmlns"
> +      end
> +      res = jsonHash.to_json          
> +    end                
> +  end        
> +end
> +
> +get "/api/collection/:collType" do
> +  if RESOURCENAMES.include? params[:collType]
> +    "#{params[:collType]}  received!"
> +    # here we will handle the update of changing the collection attribute.
> +    # no item in the collection will be changed, this will be only used to change properties of a collection.
> +
> +    puts "request params " + params.inspect
> +    #the resources should be retrieved from DeltaCloud
> +    if (SUPPORTEDRES.include? params[:collType]) 
> +      @dmtfColItems = getCollectionItemFromDC(params[:collType])
> +    else
> +      @dmtfColItems = getCollectionItem(params[:collType])
> +    end              
> +        
> +    respond_to do |format|
> +      format.html do          
> +        rootHash = XmlSimple.xml_in(File.join(STOREROOT, 'collections/' + params[:collType] + '.col.xml'), 
> +                   { 'ForceArray' => false, 'KeepRoot'=>true, 'KeyAttr' => ['name']})
> +    
> +        @xmlRootNode = rootHash.first[0]
> +        @dmtfitem = rootHash.first[1]   
> +        puts @dmtfitem   
> +        haml :"collection/index" 
> +      end
> +      format.xml do          
> +        rootHash = XmlSimple.xml_in(File.join(STOREROOT, 'collections/' + params[:collType] + '.col.xml'), 
> +                   { 'ForceArray' => true, 'KeepRoot'=>true, 'KeyAttr' => ['name']})
> +        puts rootHash.inspect
> +        colItemName = rootHash.first[0]
> +        content_type getResponseContentType(colItemName, 'xml'), :charset => 'utf-8'
> +        colItemName = colItemName.sub(/Collection/,'') #Remove the Collection at the end.
> +        colItemName = colItemName[0].downcase + colItemName[1, colItemName.length]
> +
> +        #we need to produce the url collection
> +        urls = []
> +        @dmtfColItems.map do |item|
> +          urls << {"href" => item["href"]}
> +        end
> +
> +        rootHash.first[1][0]["#{colItemName}"] = urls 
> +        
> +        XmlSimple.xml_out(rootHash, { 'KeyAttr' => 'name', 'KeepRoot' => true, 'ContentKey' => 'content'})
> +      end        
> +      format.json do                     
> +        rootHash = XmlSimple.xml_in(File.join(STOREROOT, 'collections/' + params[:collType] + '.col.xml'), 
> +                   { 'ForceArray' => false, 'KeepRoot'=>true, 'KeyAttr' => ['name']})
> +        puts rootHash.inspect
> +        colItemName = rootHash.first[0]
> +        content_type getResponseContentType(colItemName, 'json'), :charset => 'utf-8'
> +        colItemName = colItemName.sub(/Collection/,'') #Remove the Collection at the end.
> +        colItemName = colItemName[0].downcase + colItemName[1, colItemName.length]
> +
> +        puts colItemName
> +        #we need to produce the url collection
> +        urls = []
> +        @dmtfColItems.map do |item|
> +          urls << {"href" => item["href"]}
> +        end
> +
> +        rootHash.first[1]["#{colItemName}"] = urls 
> +
> +        jsonHash = rootHash.first[1]
> +        puts jsonHash.inspect
> +        if jsonHash.has_key?("xmlns")
> +          jsonHash.delete "xmlns"
> +        end
> +        fixupContent jsonHash
> +        res = jsonHash.to_json          
> +      end        
> +    end
> +  else
> +    "#{params[:collType]}  not found!"
> +  end
> +end

Wow thats a pretty long block :-) I would suggest to split this code to smaller chunks, preferably helpers or
wrap them to some class if it's possible.

> +
> +get "/api/:collType/:id" do
> +
> +  puts Time.new.to_s + " collType=" + params[:collType] + " id=" + params[:id]
> +
> +  if params[:id] == "new"
> +    filePath = File.join(STOREROOT, 'defaultRes/' + params[:collType] + '.col.xml')  
> +    puts "loading file at " + filePath
> +    if File.exist?(filePath)      
> +      rootHash = XmlSimple.xml_in(filePath, {'ForceArray'=>false, 'KeepRoot'=>true, 'KeyAttr'=>['name']})
> +      puts rootHash.inspect
> +      
> +      @xmlRootNode = rootHash.first[0]
> +      @dmtfitem = rootHash.first[1]
> +      @dmtfitem["uri"] = UUIDTools::UUID.random_create.to_s
> +      @dmtfitem["created"] = Time.new.getutc 
> +      contentPath = params[:collType] + "/new"
> +      respond_to do |format|
> +        format.html { haml contentPath.to_sym }
> +      end
> +    else
> +      report_error(404)
> +    end  
> +  else
> +    #We need to first handle special resources which already exist in DC.
> +    #then we do the resources defined locally.
> +    handleResourceGet
> +  end
> +end
> +
> +put "/api/collection/:id" do
> +  handleCollectionPut
> +end
> +
> +post "/api/:collType" do
> +  handlePost
> +end
> +
> +put "/api/:collType/:id" do
> +  handleResourcePut
> +end
> +
> +delete "/api/:collType/:id" do
> +  handleResourceDelete
> +end
> +
> diff --git a/server/lib/deltacloud/base_driver/base_driver.rb b/server/lib/deltacloud/base_driver/base_driver.rb
> index 3eb49b3..931ef5c 100644
> --- a/server/lib/deltacloud/base_driver/base_driver.rb
> +++ b/server/lib/deltacloud/base_driver/base_driver.rb
> @@ -14,7 +14,7 @@
> # License for the specific language governing permissions and limitations
> # under the License.
> 
> -require 'lib/deltacloud/base_driver/exceptions'
> +require 'deltacloud/base_driver/exceptions'
> 
> module Deltacloud
> 
> diff --git a/server/lib/deltacloud/server.rb b/server/lib/deltacloud/server.rb
> new file mode 100644
> index 0000000..6400a3f
> --- /dev/null
> +++ b/server/lib/deltacloud/server.rb
> @@ -0,0 +1,1191 @@
> +# Licensed to the Apache Software Foundation (ASF) under one or more
> +# contributor license agreements.  See the NOTICE file distributed with
> +# this work for additional information regarding copyright ownership.  The
> +# ASF licenses this file to you under the Apache License, Version 2.0 (the
> +# "License"); you may not use this file except in compliance with the
> +# License.  You may obtain a copy of the License at
> +#
> +#       http://www.apache.org/licenses/LICENSE-2.0
> +#
> +# Unless required by applicable law or agreed to in writing, software
> +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
> +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
> +# License for the specific language governing permissions and limitations
> +# under the License.
> +
> +require 'sinatra'
> +require 'deltacloud'
> +require 'json'
> +require 'sinatra/rack_accept'
> +require 'sinatra/static_assets'
> +require 'sinatra/rabbit'
> +require 'sinatra/lazy_auth'
> +require 'erb'
> +require 'haml'
> +require 'open3'
> +require 'sinatra/sinatra_verbose'
> +require 'sinatra/rack_driver_select'
> +require 'sinatra/rack_runtime'
> +require 'sinatra/rack_etag'
> +require 'sinatra/rack_date'
> +require 'sinatra/rack_matrix_params'
> +require 'sinatra/rack_syslog'
> +
> +set :version, '0.4.0'
> +
> +include Deltacloud::Drivers
> +set :drivers, Proc.new { driver_config }
> +
> +Sinatra::Application.register Rack::RespondTo
> +
> +use Rack::ETag
> +use Rack::Runtime
> +use Rack::MatrixParams
> +use Rack::DriverSelect
> +use Rack::MediaType
> +use Rack::Date
> +
> +configure do
> +  set :views, File::join($top_srcdir, 'views')
> +  set :public, File::join($top_srcdir, 'public')
> +  # Try to load the driver on startup to fail early if there are issues
> +  driver
> +end
> +
> +configure :production do
> +  use Rack::SyslogLogger
> +  disable :logging
> +  enable :show_errors
> +  set :dump_errors, false
> +  $stdout = SyslogFile.new
> +  $stderr = $stdout
> +end
> +
> +configure :development do
> +  # So we can just use puts for logging
> +  set :raise_errors => false
> +  set :show_exceptions, false
> +  $stdout.sync = true
> +  $stderr.sync = true
> +end
> +
> +# You could use $API_HOST environment variable to change your hostname to
> +# whatever you want (eg. if you running API behind NAT)
> +HOSTNAME=ENV['API_HOST'] ? ENV['API_HOST'] : nil
> +
> +error do
> +  report_error
> +end
> +
> +# Redirect to /api
> +get '/' do redirect root_url, 301; end
> +
> +get "#{Sinatra::UrlForHelper::DEFAULT_URI_PREFIX}\/?" do
> +  if params[:force_auth]
> +    return [401, 'Authentication failed'] unless driver.valid_credentials?(credentials)
> +  end
> +  @collections = [:drivers] + driver.supported_collections
> +  respond_to do |format|
> +    format.xml { haml :"api/show" }
> +    format.json do
> +      { :api => {
> +          :version => settings.version,
> +          :driver => driver_symbol,
> +          :links => entry_points.collect do |l|
> +            { :rel => l[0], :href => l[1] }.merge(json_features_for_entrypoint(l))
> +          end
> +        }
> +      }.to_json
> +    end
> +    format.html { haml :"api/show" }
> +  end
> +end
> +
> +# Rabbit DSL
> +
> +collection :drivers do
> +  global!
> +
> +  description <<EOS
> +List all the drivers supported by this server.
> +EOS
> +
> +  operation :index do
> +    description "List all drivers"
> +    control do
> +      @drivers = settings.drivers
> +      respond_to do |format|
> +        format.xml { haml :"drivers/index" }
> +        format.json { @drivers.to_json }
> +        format.html { haml :"drivers/index" }
> +      end
> +    end
> +  end
> +
> +  operation :show do
> +    description "Show details for a driver"
> +    param :id,      :string
> +    control do
> +      @name = params[:id].to_sym
> +      @driver = settings.drivers[@name]
> +      return [404, "Driver #{@name} not found"] unless @driver
> +      respond_to do |format|
> +        format.xml { haml :"drivers/show" }
> +        format.json { @driver.to_json }
> +        format.html { haml :"drivers/show" }
> +      end
> +    end
> +  end
> +end
> +
> +collection :realms do
> +  description <<END
> +  Within a cloud provider a realm represents a boundary containing resources.
> +  The exact definition of a realm is left to the cloud provider.
> +  In some cases, a realm may represent different datacenters, different continents,
> +  or different pools of resources within a single datacenter.
> +  A cloud provider may insist that resources must all exist within a single realm in
> +  order to cooperate. For instance, storage volumes may only be allowed to be mounted to
> +  instances within the same realm.
> +END
> +
> +  operation :index do
> +    description <<END
> +    Operation will list all available realms. Realms can be filtered using
> +    the "architecture" parameter.
> +END
> +    with_capability :realms
> +    param :id,            :string
> +    param :architecture,  :string,  :optional,  [ 'i386', 'x86_64' ]
> +    control { filter_all(:realms) }
> +  end
> +
> +  #FIXME: It always shows whole list
> +  operation :show do
> +    description 'Show an realm identified by "id" parameter.'
> +    with_capability :realm
> +    param :id,           :string, :required
> +    control { show(:realm) }
> +  end
> +
> +end
> +
> +collection :images do
> +  description <<END
> +  An image is a platonic form of a machine. Images are not directly executable,
> +  but are a template for creating actual instances of machines.
> +END
> +
> +  operation :new do
> +    description "Form to create a new image resource"
> +    param :instance_id, :string,  "An instance from which the new image will be created from"
> +    control do
> +      @instance = Instance.new( :id => params[:instance_id] )
> +      respond_to do |format|
> +        format.html { haml :"images/new" }
> +      end
> +    end
> +  end
> +
> +  operation :index do
> +    description <<END
> +    The images collection will return a set of all images
> +    available to the current use. Images can be filtered using the
> +    "owner_id" and "architecture" parameters.
> +END
> +    with_capability :images
> +    param :id,            :string
> +    param :architecture,  :string,  :optional
> +    control { filter_all(:images) }
> +  end
> +
> +  operation :show do
> +    description 'Show an image identified by "id" parameter.'
> +    with_capability :image
> +    param :id,           :string, :required
> +    control { show(:image) }
> +  end
> +
> +  operation :create do
> +    description 'Create image from instance'
> +    with_capability :create_image
> +    param :instance_id,	 :string, :required
> +    param :name,	 :string, :optional
> +    param :description,	 :string, :optional
> +    control do
> +      @image = driver.create_image(credentials, {
> +	:id => params[:instance_id],
> +        :name => params[:name],
> +	:description => params[:description]
> +      })
> +      status 201  # Created
> +      response['Location'] = image_url(@instance.id)
> +      respond_to do |format|
> +        format.xml  { haml :"images/show" }
> +        format.json { convert_to_json(:image, @image) }
> +        format.html { haml :"images/show" }
> +      end
> +    end
> +  end
> +
> +  operation :destroy do
> +    description "Remove specified image from collection"
> +    with_capability :destroy_image
> +    param :id,    :string,    :required
> +    control do
> +      driver.destroy_image(credentials, params[:id])
> +      status 204
> +      respond_to do |format|
> +        format.xml
> +        format.json
> +        format.html { redirect(images_url) }
> +      end
> +    end
> +  end
> +
> +end
> +
> +collection :instance_states do
> +  description "The possible states of an instance, and how to traverse between them "
> +
> +  operation :index do
> +    control do
> +      @machine = driver.instance_state_machine
> +      respond_to do |format|
> +        format.xml { haml :'instance_states/show', :layout => false }
> +        format.json do
> +          out = []
> +          @machine.states.each do |state|
> +            transitions = state.transitions.collect do |t|
> +              t.automatically? ? {:to => t.destination, :auto => 'true'} : {:to => t.destination, :action => t.action}
> +            end
> +            out << { :name => state, :transitions => transitions }
> +          end
> +          out.to_json
> +        end
> +        format.html { haml :'instance_states/show'}
> +        format.gv { erb :"instance_states/show" }
> +        format.png do
> +          # Trick respond_to into looking up the right template for the
> +          # graphviz file
> +          gv = erb(:"instance_states/show")
> +          png =  ''
> +          cmd = 'dot -Kdot -Gpad="0.2,0.2" -Gsize="5.0,8.0" -Gdpi="180" -Tpng'
> +          Open3.popen3( cmd ) do |stdin, stdout, stderr|
> +            stdin.write( gv )
> +            stdin.close()
> +            png = stdout.read
> +          end
> +          content_type 'image/png'
> +          png
> +        end
> +      end
> +    end
> +  end
> +end
> +
> +get "#{Sinatra::UrlForHelper::DEFAULT_URI_PREFIX}/instances/:id/run" do
> +  @instance = driver.instance(credentials, :id => params[:id])
> +  respond_to do |format|
> +    format.html { haml :"instances/run_command" }
> +  end
> +end
> +
> +collection :load_balancers do
> +  description "Load balancers"
> +
> +  operation :new do
> +    description "Form to create a new load balancer"
> +    control do
> +      @realms = driver.realms(credentials)
> +      @instances = driver.instances(credentials) if driver_has_feature?(:register_instance, :load_balancers)
> +      respond_to do |format|
> +        format.html { haml :"load_balancers/new" }
> +      end
> +    end
> +  end
> +
> +  operation :index do
> +    description "List of all active load balancers"
> +    control do
> +      filter_all :load_balancers
> +    end
> +  end
> +
> +  operation :show do
> +    description "Show details about given load balancer"
> +    param :id,  :string,  :required
> +    control { show :load_balancer }
> +  end
> +
> +  operation :create do
> +    description "Create a new load balancer"
> +    param :name,  :string,  :required
> +    param :realm_id,  :string,  :required
> +    param :listener_protocol,  :string,  :required, ['HTTP', 'TCP']
> +    param :listener_balancer_port,  :string,  :required
> +    param :listener_instance_port,  :string,  :required
> +    control do
> +      @load_balancer = driver.create_load_balancer(credentials, params)
> +      status 201  # Created
> +      response['Location'] = load_balancer_url(@instance.id)
> +      respond_to do |format|
> +        format.xml  { haml :"load_balancers/show" }
> +        format.json { convert_to_json(:load_balancer, @load_balancer) }
> +        format.html { haml :"load_balancers/show" }
> +      end
> +    end
> +  end
> +
> +  operation :register, :method => :post, :member => true do
> +    description "Add instance to loadbalancer"
> +    param :id,  :string,  :required
> +    param :instance_id, :string,  :required
> +    control do
> +      driver.lb_register_instance(credentials, params)
> +      status 204
> +      respond_to do |format|
> +        format.xml
> +        format.json
> +        format.html { redirect(load_balancer_url(params[:id])) }
> +      end
> +    end
> +  end
> +
> +  operation :unregister, :method => :post, :member => true do
> +    description "Remove instance from loadbalancer"
> +    param :id,  :string,  :required
> +    param :instance_id, :string,  :required
> +    control do
> +      driver.lb_unregister_instance(credentials, params)
> +      status 204
> +      respond_to do |format|
> +        format.xml
> +        format.json
> +        format.html { redirect(load_balancer_url(params[:id])) }
> +      end
> +    end
> +  end
> +
> +  operation :destroy do
> +    description "Destroy given load balancer"
> +    param :id,  :string,  :required
> +    control do
> +      driver.destroy_load_balancer(credentials, params[:id])
> +      status 204
> +      respond_to do |format|
> +        format.xml
> +        format.json
> +        format.html { redirect(load_balancers_url) }
> +      end
> +    end
> +  end
> +
> +end
> +
> +
> +collection :instances do
> +  description <<END
> +  An instance is a concrete machine realized from an image.
> +  The images collection may be obtained by following the link from the primary entry-point.
> +END
> +
> +  operation :new do
> +    description "Form for creating a new instance resource"
> +    param :image_id,  :string,  "Image from which will be the new instance created from"
> +    param :realm_id,  :string, :optional
> +    if driver_has_feature? :authentication_key
> +      param :authentication_key, :string, :optional
> +    end
> +    if driver_has_feature? :firewalls
> +      param :firewalls, :string, :optional
> +    end
> +    control do
> +      @instance = Instance.new( { :id=>params[:id], :image_id=>params[:image_id] } )
> +      @image   = Image.new( :id => params[:image_id] )
> +      @hardware_profiles = driver.hardware_profiles(credentials, :architecture => @image.architecture )
> +      @realms = [Realm.new(:id => params[:realm_id])] if params[:realm_id]
> +      @realms ||= driver.realms(credentials)
> +      @keys = driver.keys(credentials) if driver_has_feature?(:authentication_key)
> +      @firewalls = driver.firewalls(credentials) if driver_has_feature?(:firewalls)
> +      respond_to do |format|
> +        format.html do
> +          haml :'instances/new'
> +        end
> +      end
> +    end
> +  end
> +
> +  operation :index do
> +    description "List all instances."
> +    with_capability :instances
> +    param :id,            :string,  :optional
> +    param :state,         :string,  :optional
> +    control { filter_all(:instances) }
> +  end
> +
> +  operation :show do
> +    description 'Show an instance identified by "id" parameter.'
> +    with_capability :instance
> +    param :id,           :string, :required
> +    control { show(:instance) }
> +  end
> +
> +  operation :create do
> +    description "Create a new instance."
> +    with_capability :create_instance
> +    param :image_id,     :string, :required
> +    param :realm_id,     :string, :optional
> +    param :hwp_id,       :string, :optional
> +    control do
> +      @instance = driver.create_instance(credentials, params[:image_id], params)
> +      status 201  # Created
> +      response['Location'] = instance_url(@instance.id)
> +      respond_to do |format|
> +        format.xml  { haml :"instances/show" }
> +        format.json { convert_to_json(:instance, @instance) }
> +        format.html do
> +          redirect instance_url(@instance.id) if @instance and @instance.id
> +          redirect instances_url
> +        end
> +      end
> +    end
> +  end
> +
> +  operation :reboot, :method => :post, :member => true do
> +    description "Reboot a running instance."
> +    with_capability :reboot_instance
> +    param :id,           :string, :required
> +    control { instance_action(:reboot) }
> +  end
> +
> +  operation :start, :method => :post, :member => true do
> +    description "Start an instance."
> +    with_capability :start_instance
> +    param :id,           :string, :required
> +    control { instance_action(:start) }
> +  end
> +
> +  operation :stop, :method => :post, :member => true do
> +    description "Stop a running instance."
> +    with_capability :stop_instance
> +    param :id,           :string, :required
> +    control { instance_action(:stop) }
> +  end
> +
> +  operation :destroy do
> +    description "Destroy an instance."
> +    with_capability :destroy_instance
> +    param :id,           :string, :required
> +    control { instance_action(:destroy) }
> +  end
> +
> +  operation :run, :method => :post, :member => true do
> +    description <<END
> +  Run command on instance. Either password or private key must be send
> +  in order to execute command. Authetication method should be advertised
> +  in instance.
> +END
> +    with_capability :run_on_instance
> +    param :id,          :string,  :required
> +    param :cmd,         :string,  :required, [], "Shell command to run on instance"
> +    param :private_key, :string,  :optional, [], "Private key in PEM format for authentication"
> +    param :password,    :string,  :optional, [], "Password used for authentication"
> +    control do
> +      @output = driver.run_on_instance(credentials, params)
> +      respond_to do |format|
> +        format.xml { haml :"instances/run" }
> +        format.html { haml :"instances/run" }
> +      end
> +    end
> +  end
> +end
> +
> +collection :hardware_profiles do
> +  description <<END
> + A hardware profile represents a configuration of resources upon which a
> + machine may be deployed. It defines aspects such as local disk storage,
> + available RAM, and architecture. Each provider is free to define as many
> + (or as few) hardware profiles as desired.
> +END
> +
> +  operation :index do
> +    description "List of available hardware profiles."
> +    with_capability :hardware_profiles
> +    param :id,          :string
> +    param :architecture,  :string,  :optional,  [ 'i386', 'x86_64' ]
> +    control do
> +        @profiles = driver.hardware_profiles(credentials, params)
> +        respond_to do |format|
> +          format.xml  { haml :'hardware_profiles/index' }
> +          format.html  { haml :'hardware_profiles/index' }
> +          format.json { convert_to_json(:hardware_profile, @profiles) }
> +        end
> +    end
> +  end
> +
> +  operation :show do
> +    description "Show specific hardware profile."
> +    with_capability :hardware_profile
> +    param :id,          :string,    :required
> +    control do
> +      @profile =  driver.hardware_profile(credentials, params[:id])
> +      if @profile
> +        respond_to do |format|
> +          format.xml { haml :'hardware_profiles/show', :layout => false }
> +          format.html { haml :'hardware_profiles/show' }
> +          format.json { convert_to_json(:hardware_profile, @profile) }
> +        end
> +      else
> +        report_error(404)
> +      end
> +    end
> +  end
> +
> +end
> +
> +collection :storage_snapshots do
> +  description "Storage snapshots description here"
> +
> +  operation :new do
> +    description "A form to create a new storage snapshot"
> +    control do
> +      respond_to do |format|
> +        format.html { haml :"storage_snapshots/new" }
> +      end
> +    end
> +  end
> +
> +  operation :index do
> +    description "List of storage snapshots."
> +    with_capability :storage_snapshots
> +    param :id,            :string
> +    control { filter_all(:storage_snapshots) }
> +  end
> +
> +  operation :show do
> +    description "Show storage snapshot."
> +    with_capability :storage_snapshot
> +    param :id,          :string,    :required
> +    control { show(:storage_snapshot) }
> +  end
> +
> +  operation :create do
> +    description "Create a new snapshot from volume"
> +    with_capability :create_storage_snapshot
> +    param :volume_id, :string,  :required
> +    control do
> +      @storage_snapshot = driver.create_storage_snapshot(credentials, params)
> +      status 201  # Created
> +      response['Location'] = storage_snapshot_url(@storage_snapshot.id)
> +      show(:storage_snapshot)
> +    end
> +  end
> +
> +  operation :destroy do
> +    description "Delete storage snapshot"
> +    with_capability :destroy_storage_snapshot
> +    param :id,  :string,  :required
> +    control do
> +      driver.destroy_storage_snapshot(credentials, params)
> +      status 204
> +      respond_to do |format|
> +        format.xml
> +        format.json
> +        format.html { redirect(storage_snapshots_url) }
> +      end
> +    end
> +  end
> +end
> +
> +collection :storage_volumes do
> +  description "Storage volumes description here"
> +
> +  operation :new do
> +    description "A form to create a new storage volume"
> +    control do
> +      respond_to do |format|
> +        format.html { haml :"storage_volumes/new" }
> +      end
> +    end
> +  end
> +
> +  operation :index do
> +    description "List of storage volumes."
> +    with_capability :storage_volumes
> +    param :id,            :string
> +    control { filter_all(:storage_volumes) }
> +  end
> +
> +  operation :show do
> +    description "Show storage volume."
> +    with_capability :storage_volume
> +    param :id,          :string,    :required
> +    control { show(:storage_volume) }
> +  end
> +
> +  operation :create do
> +    description "Create a new storage volume"
> +    with_capability :create_storage_volume
> +    param :snapshot_id, :string,  :optional
> +    param :capacity,    :string,  :optional
> +    param :realm_id,    :string,  :optional
> +    control do
> +      @storage_volume = driver.create_storage_volume(credentials, params)
> +      status 201
> +      response['Location'] = storage_volume_url(@storage_volume.id)
> +      respond_to do |format|
> +        format.xml  { haml :"storage_volumes/show" }
> +        format.html { haml :"storage_volumes/show" }
> +        format.json { convert_to_json(:storage_volume, @storage_volume) }
> +      end
> +    end
> +  end
> +
> +  operation :attach, :method => :post, :member => true do
> +    description "Attach storage volume to instance"
> +    with_capability :attach_storage_volume
> +    param :id,         :string,  :required
> +    param :instance_id,:string,  :required
> +    param :device,     :string,  :required
> +    control do
> +      @storage_volume = driver.attach_storage_volume(credentials, params)
> +      status 202
> +      respond_to do |format|
> +        format.html { redirect(storage_volume_url(params[:id]))}
> +        format.xml  { haml :"storage_volumes/show" }
> +        format.json { convert_to_json(:storage_volume, @storage_volume) }
> +      end
> +    end
> +  end
> +
> +  operation :detach, :method => :post, :member => true do
> +    description "Detach storage volume to instance"
> +    with_capability :detach_storage_volume
> +    param :id,         :string,  :required
> +    control do
> +      volume = driver.storage_volume(credentials, :id => params[:id])
> +      @storage_volume =  driver.detach_storage_volume(credentials, :id => volume.id, :instance_id => volume.instance_id, :device => volume.device)
> +      status 202
> +      respond_to do |format|
> +        format.html { redirect(storage_volume_url(params[:id]))}
> +        format.xml  { haml :"storage_volumes/show" }
> +        format.json { convert_to_json(:storage_volume, @storage_volume) }
> +      end
> +    end
> +  end
> +
> +  operation :destroy do
> +    description "Destroy storage volume"
> +    with_capability :destroy_storage_volume
> +    param :id,          :string,  :optional
> +    control do
> +      driver.destroy_storage_volume(credentials, params)
> +      status 204
> +      respond_to do |format|
> +        format.xml
> +        format.json
> +        format.html { redirect(storage_volumes_url) }
> +      end
> +    end
> +  end
> +
> +end
> +
> +collection :keys do
> +  description "Instance authentication credentials."
> +
> +  operation :new do
> +    description "A form to create a new key resource"
> +    control do
> +      respond_to do |format|
> +        format.html { haml :"keys/new" }
> +      end
> +    end
> +  end
> +
> +  operation :index do
> +    description "List all available credentials which could be used for instance authentication."
> +    with_capability :keys
> +    control do
> +      filter_all :keys
> +    end
> +  end
> +
> +  operation :show do
> +    description "Show details about given instance credential."
> +    with_capability :key
> +    param :id,  :string,  :required
> +    control { show :key }
> +  end
> +
> +  operation :create do
> +    description "Create a new instance credential if backend supports this."
> +    with_capability :create_key
> +    param :name,  :string,  :required
> +    control do
> +      @key = driver.create_key(credentials, { :key_name => params[:name] })
> +      status 201
> +      response['Location'] = key_url(@key.id)
> +      respond_to do |format|
> +        format.xml  { haml :"keys/show", :ugly => true }
> +        format.html { haml :"keys/show" }
> +        format.json { convert_to_json(:key, @key)}
> +      end
> +    end
> +  end
> +
> +  operation :destroy do
> +    description "Destroy given instance credential if backend supports this."
> +    with_capability :destroy_key
> +    param :id,  :string,  :required
> +    control do
> +      driver.destroy_key(credentials, { :id => params[:id]})
> +      status 204
> +      respond_to do |format|
> +        format.xml
> +        format.json
> +        format.html { redirect(keys_url) }
> +      end
> +    end
> +  end
> +
> +end
> +
> +#get html form for creating a new blob
> +
> +# The URL for getting the new blob form for the HTML UI looks like the URL
> +# for getting the details of an existing blob. To make collisions less
> +# likely, we use a name for the form that will rarely be the name of an
> +# existing blob
> +NEW_BLOB_FORM_ID = "new_blob_form_d15cfd90"
> +
> +get "#{Sinatra::UrlForHelper::DEFAULT_URI_PREFIX}/buckets/:bucket/#{NEW_BLOB_FORM_ID}" do
> +  @bucket_id = params[:bucket]
> +  respond_to do |format|
> +    format.html {haml :"blobs/new"}
> +  end
> +end
> +
> +collection :buckets do
> +  description "Cloud Storage buckets - aka buckets|directories|folders"
> +
> +  collection :blobs do
> +    description "Blobs associated with given bucket"
> +
> +    operation :show do
> +      description "Display blob"
> +      control do
> +        @blob = driver.blob(credentials, { :id => params[:blob], 'bucket' => params[:bucket]})
> +        if @blob
> +          respond_to do |format|
> +            format.xml { haml :"blobs/show" }
> +            format.html { haml :"blobs/show" }
> +            format.json { convert_to_json(:blob, @blob) }
> +          end
> +        else
> +          report_error(404)
> +        end
> +      end
> +
> +    end
> +
> +    operation :create do
> +      description "Create new blob"
> +      control do
> +        bucket_id = params[:bucket]
> +        blob_id = params['blob_id']
> +        blob_data = params['blob_data']
> +        user_meta = {}
> +        #metadata from params (i.e., passed by http form post, e.g. browser)
> +        max = params[:meta_params]
> +        if(max)
> +          (1..max.to_i).each do |i|
> +            key = params[:"meta_name#{i}"]
> +            key = "HTTP_X_Deltacloud_Blobmeta_#{key}"
> +            value = params[:"meta_value#{i}"]
> +            user_meta[key] = value
> +          end
> +        end
> +        @blob = driver.create_blob(credentials, bucket_id, blob_id, blob_data, user_meta)
> +        respond_to do |format|
> +          format.xml { haml :"blobs/show" }
> +          format.html { haml :"blobs/show"}
> +        end
> +      end
> +    end
> +
> +    operation :destroy do
> +      description "Destroy given blob"
> +      control do
> +        bucket_id = params[:bucket]
> +        blob_id = params[:blob]
> +        driver.delete_blob(credentials, bucket_id, blob_id)
> +        status 204
> +        respond_to do |format|
> +          format.xml
> +          format.json
> +          format.html { redirect(bucket_url(bucket_id)) }
> +        end
> +      end
> +    end
> +
> +    operation :stream, :member => true, :standard => true, :method => :put do
> +      description "Stream new blob data into the blob"
> +      control do
> +        if(env["BLOB_SUCCESS"]) #ie got a 200ok after putting blob
> +          content_type = env["CONTENT_TYPE"]
> +          content_type ||=  ""
> +          @blob = driver.blob(credentials, {:id => params[:blob],
> +                                            'bucket' => params[:bucket]})
> +          respond_to do |format|
> +            format.xml { haml :"blobs/show" }
> +            format.html { haml :"blobs/show" }
> +            format.json { convert_to_json(:blob, @blob) }
> +          end
> +        elsif(env["BLOB_FAIL"])
> +          report_error(500) #OK?
> +        else # small blobs - < 112kb dont hit the streaming monkey patch - use 'normal' create_blob
> +          # also, if running under webrick don't hit the streaming patch (Thin specific)
> +          bucket_id = params[:bucket]
> +          blob_id = params[:blob]
> +          temp_file = Tempfile.new("temp_blob_file")
> +          temp_file.write(env['rack.input'].read)
> +          temp_file.flush
> +          content_type = env['CONTENT_TYPE'] || ""
> +          blob_data = {:tempfile => temp_file, :type => content_type}
> +          user_meta = BlobHelper::extract_blob_metadata_hash(request.env)
> +          @blob = driver.create_blob(credentials, bucket_id, blob_id, blob_data, user_meta)
> +          temp_file.delete
> +          respond_to do |format|
> +            format.xml { haml :"blobs/show" }
> +            format.html { haml :"blobs/show"}
> +          end
> +        end
> +      end
> +    end
> +
> +    operation :metadata, :member => true, :standard => true, :method => :head do
> +      description "Get blob metadata"
> +      control do
> +        @blob_id = params[:blob]
> +        @blob_metadata = driver.blob_metadata(credentials, {:id => params[:blob], 'bucket' => params[:bucket]})
> +        if @blob_metadata
> +          @blob_metadata.each do |k,v|
> +            headers["X-Deltacloud-Blobmeta-#{k}"] = v
> +          end
> +          status 204
> +          respond_to do |format|
> +            format.xml
> +            format.json
> +          end
> +        else
> +          report_error(404)
> +        end
> +      end
> +    end
> +
> +    operation :update, :member => true, :method => :post do
> +      description "Update blob metadata"
> +      control do
> +        meta_hash = BlobHelper::extract_blob_metadata_hash(request.env)
> +        success = driver.update_blob_metadata(credentials, {'bucket'=>params[:bucket], :id =>params[:blob], 'meta_hash' => meta_hash})
> +        if(success)
> +          meta_hash.each do |k,v|
> +            headers["X-Deltacloud-Blobmeta-#{k}"] = v
> +          end
> +          status 204
> +          respond_to do |format|
> +            format.xml
> +            format.json
> +          end
> +        else
> +          report_error(404) #FIXME is this the right error code?
> +        end
> +      end
> +    end
> +
> +    operation :content, :member => true, :method => :get do
> +      description "Download blob content"
> +      control do
> +        @blob = driver.blob(credentials, { :id => params[:blob], 'bucket' => params[:bucket]})
> +        if @blob
> +          params['content_length'] = @blob.content_length
> +          params['content_type'] = @blob.content_type
> +          params['content_disposition'] = "attachment; filename=#{@blob.id}"
> +          BlobStream.call(env, credentials, params)
> +        else
> +          report_error(404)
> +        end
> +      end
> +    end
> +
> +  end
> +
> +  operation :new do
> +    description "A form to create a new bucket resource"
> +    control do
> +      respond_to do |format|
> +        format.html { haml :"buckets/new" }
> +      end
> +    end
> +  end
> +
> +  operation :index do
> +    description "List buckets associated with this account"
> +    with_capability :buckets
> +    param :id,        :string
> +    param :name,      :string
> +    param :size,      :string
> +    control { filter_all(:buckets) }
> +  end
> +
> +  operation :show do
> +    description "Show bucket"
> +    with_capability :bucket
> +    param :id,        :string
> +    control { show(:bucket) }
> +  end
> +
> +  operation :create do
> +    description "Create a new bucket (POST /api/buckets)"
> +    with_capability :create_bucket
> +    param :name,      :string,    :required
> +    control do
> +      @bucket = driver.create_bucket(credentials, params[:name], params)
> +      status 201
> +      response['Location'] = bucket_url(@bucket.id)
> +      respond_to do |format|
> +        format.xml  { haml :"buckets/show" }
> +        format.json { convert_to_json(:bucket, @bucket) }
> +        format.html do
> +          redirect bucket_url(@bucket.id) if @bucket and @bucket.id
> +          redirect buckets_url
> +        end
> +      end
> +    end
> +  end
> +
> +  operation :destroy do
> +    description "Delete a bucket by name - bucket must be empty"
> +    with_capability :delete_bucket
> +    param :id,    :string,    :required
> +    control do
> +      driver.delete_bucket(credentials, params[:id], params)
> +      status 204
> +      respond_to do |format|
> +        format.xml
> +        format.json
> +        format.html {  redirect(buckets_url) }
> +      end
> +    end
> +  end
> +
> +end
> +
> +get "#{Sinatra::UrlForHelper::DEFAULT_URI_PREFIX}/addresses/:id/associate" do
> +  @instances = driver.instances(credentials)
> +  @address = Address::new(:id => params[:id])
> +  respond_to do |format|
> +    format.html { haml :"addresses/associate" }
> +  end
> +end
> +
> +collection :addresses do
> +  description "Manage IP addresses"
> +
> +  operation :index do
> +    description "List IP addresses assigned to your account."
> +    with_capability :addresses
> +    control do
> +      filter_all :addresses
> +    end
> +  end
> +
> +  operation :show do
> +    description "Show details about IP addresses specified by given ID"
> +    with_capability :address
> +    param :id,  :string,  :required
> +    control { show :address }
> +  end
> +
> +  operation :create do
> +    description "Acquire a new IP address for use with your account."
> +    with_capability :create_address
> +    control do
> +      @address = driver.create_address(credentials, {})
> +      status 201    # Created
> +      response['Location'] = address_url(@address.id)
> +      respond_to do |format|
> +        format.xml  { haml :"addresses/show", :ugly => true }
> +        format.html { haml :"addresses/_address", :layout => false }
> +        format.json { convert_to_json(:address, @address) }
> +      end
> +    end
> +  end
> +
> +  operation :destroy do
> +    description "Release an IP address associated with your account"
> +    with_capability :destroy_address
> +    param :id,  :string,  :required
> +    control do
> +      driver.destroy_address(credentials, { :id => params[:id]})
> +      status 204
> +      respond_to do |format|
> +        format.xml
> +        format.json
> +        format.html { redirect(addresses_url) }
> +      end
> +    end
> +  end
> +
> +  operation :associate, :method => :post, :member => true do
> +    description "Associate an IP address to an instance"
> +    with_capability :associate_address
> +    param :id, :string, :required
> +    param :instance_id, :string, :required
> +    control do
> +      driver.associate_address(credentials, { :id => params[:id], :instance_id => params[:instance_id]})
> +      status 202   # Accepted
> +      respond_to do |format|
> +        format.xml
> +        format.json
> +        format.html { redirect(address_url(params[:id])) }
> +      end
> +    end
> +  end
> +
> +  operation :disassociate, :method => :post, :member => true do
> +    description "Disassociate an IP address from an instance"
> +    with_capability :associate_address
> +    param :id, :string, :required
> +    control do
> +      driver.disassociate_address(credentials, { :id => params[:id] })
> +      status 202   # Accepted
> +      respond_to do |format|
> +        format.xml
> +        format.json
> +        format.html { redirect(address_url(params[:id])) }
> +      end
> +    end
> +  end
> +
> +end
> +
> +#delete a firewall rule
> +delete '/api/firewalls/:firewall/:rule' do
> +  opts = {}
> +  opts[:firewall] = params[:firewall]
> +  opts[:rule_id] = params[:rule]
> +  driver.delete_firewall_rule(credentials, opts)
> +  status 204
> +  respond_to do |format|
> +    format.xml
> +    format.json
> +    format.html {redirect firewall_url(params[:firewall])}
> +  end
> +end
> +
> +#FIREWALLS
> +collection :firewalls do
> +  description "Allow user to define firewall rules for an instance (ec2 security groups) eg expose ssh access [port 22, tcp]."
> +
> +  operation :new do
> +    description "A form to create a new firewall resource"
> +    control do
> +      respond_to do |format|
> +        format.html { haml :"firewalls/new" }
> +      end
> +    end
> +  end
> +
> +  operation :new_rule, :form => true, :member => true, :method => :get do
> +    description "A form to create a new firewall rule"
> +    param :id,  :string,  :required
> +    control do
> +      @firewall_name = params[:id]
> +      respond_to do |format|
> +        format.html {haml :"firewalls/new_rule" }
> +      end
> +    end
> +  end
> +
> +  operation :index do
> +    description 'List all firewalls'
> +    with_capability :firewalls
> +    control { filter_all(:firewalls) }
> +  end
> +
> +  operation :show do
> +    description 'Show details for a specific firewall - list all rules'
> +    with_capability :firewall
> +    param :id,            :string,    :required
> +    control { show(:firewall) }
> +  end
> +
> +  operation :create do
> +    description 'Create a new firewall'
> +    with_capability :create_firewall
> +    param :name,          :string,    :required
> +    param :description,   :string,    :required
> +    control do
> +      @firewall = driver.create_firewall(credentials, params )
> +      status 201  # Created
> +      response['Location'] = firewall_url(@firewall.id)
> +      respond_to do |format|
> +        format.xml  { haml :"firewalls/show" }
> +        format.html { haml :"firewalls/show" }
> +        format.json { convert_to_json(:firewall, @firewall) }
> +      end
> +    end
> +  end
> +
> +  operation :destroy do
> +    description 'Delete a specified firewall - error if firewall has rules'
> +    with_capability :delete_firewall
> +    param :id,            :string,    :required
> +    control do
> +      driver.delete_firewall(credentials, params)
> +      status 204
> +      respond_to do |format|
> +        format.xml
> +        format.json
> +        format.html {  redirect(firewalls_url) }
> +      end
> +    end
> +  end
> +
> +  #create a new firewall rule - POST /api/firewalls/:firewall/rules
> +  operation :rules, :method => :post, :member => true do
> +    description 'Create a new firewall rule for the specified firewall'
> +    param :id,  :required, :string, [],  "Name of firewall in which to apply this rule"
> +    param :protocol,  :required, :string, ['tcp','udp','icmp'], "Transport layer protocol for the rule"
> +    param :port_from, :required, :string, [], "Start of port range for the rule"
> +    param :port_to,   :required, :string, [], "End of port range for the rule"
> +    with_capability :create_firewall_rule
> +    control do
> +      #source IPs from params
> +      addresses =  params.inject([]){|result,current| result << current.last unless current.grep(/^ip[-_]address/i).empty?; result}
> +      #source groups from params
> +      groups = {}
> +      max_groups  = params.select{|k,v| k=~/^group/}.size/2
> +      for i in (1..max_groups) do
> +        groups.merge!({params["group#{i}"]=>params["group#{i}owner"]})
> +      end
> +      params['addresses'] = addresses
> +      params['groups'] = groups
> +      if addresses.empty? && groups.empty?
> +        raise Deltacloud::Validation::Failure.new(nil, "No sources. Specify at least one source ip_address or group")
> +      end
> +      driver.create_firewall_rule(credentials, params)
> +      @firewall = driver.firewall(credentials, {:id => params[:id]})
> +      status 201
> +      respond_to do |format|
> +        format.xml  { haml :"firewalls/show" }
> +        format.html { haml :"firewalls/show" }
> +        format.json { convert_to_json(:firewall, @firewall) }
> +      end
> +    end
> +  end
> +
> +end
> diff --git a/server/lib/sinatra/rack_syslog.rb b/server/lib/sinatra/rack_syslog.rb
> index a73ff31..f515afb 100644
> --- a/server/lib/sinatra/rack_syslog.rb
> +++ b/server/lib/sinatra/rack_syslog.rb
> @@ -1,5 +1,5 @@
> require 'syslog'
> -require 'lib/sinatra/body_proxy'
> +require 'sinatra/body_proxy'
> 
> class SyslogFile < File
> 
> diff --git a/server/public/images/bread-bg.png b/server/public/images/bread-bg.png
> new file mode 100644
> index 0000000000000000000000000000000000000000..7321df4be23ef125db28eca29804e51f4c9d547d
> GIT binary patch
> literal 257
> zcmeAS@N?(olHy`uVBq!ia0vp^%s?#4!3HFomxovaDaPU;cPEB*=VV?2Ic!PZ?k)`P
> zK(H(Gg9uQBv%n*=n1O*?7=#%aX3dcR3bL1Y`ns~;W@O_Q)mT(KQ6DHIS>hT|;+&tG
> zo0?a`;9QiNSdyBeP@Y+mq2TW68xY>eCk|8;<LTlUB5^si|D>QxAP3WK-Ov7?SRcv6
> zyy{mMclfY3oPlHICQ*emO79mKUn!6>n<FMLRpJL1&q{@x{Z0!`tFszRP!iel_NiT<
> t9p8uhj;|t>{coH$o}OnWqrChN!!}+X4f}&fynyyFc)I$ztaD0e0svnpP4WN$
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/server/public/images/logo-wide.png b/server/public/images/logo-wide.png
> new file mode 100644
> index 0000000000000000000000000000000000000000..1f36b7ae63f6d724bca204b239dddacd0356e64b
> GIT binary patch
> literal 8333
> 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
> X*dNO=ATyQR00000NkvXXu0mjffGIyF
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/server/public/images/topbar-bg.png b/server/public/images/topbar-bg.png
> new file mode 100644
> index 0000000000000000000000000000000000000000..969ac486208ac14107c1a0de31a2c01bb6375aa1
> GIT binary patch
> literal 72084
> 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%0A_F<-lmRmrFRjU%oof
> zaZ4`ckT<`^rd(#70b)0L@X>+jHj9Ak7n|!4N+qFN)UaN~UK3G<m`I3N+&?2);NrUq
> zJw~G3`8lxK9*G_nN~N7aF+|p)sxvv4TI@%`ch_79&tg~4^?9h|gLn>uO;MU{Lrpv9
> zINZ%62t7w)N%V3SRq<oxaFLFEyn_NHcGWz?xu>a4{w7y52h5y!Svk_@Wab$3At9@1
> zop)&_?_SJ6MFPV|W@CiCPwne_Gm_$qIo{4X+ZlS&vquv&q!E}rNF7sFOb0ams0;5l
> z5G!ttAYW+TO2ORaZRq$#D!hQo;SFsoyv9d1zb{oFz(mSGPSe^){L}W1W}EcFRnES7
> zf!vc}u@T!UENFCmG=J;bJZX_p9tm5l!x5a|ToL@VVkKJfCs{eI5eRLLWUemjaEsVS
> zt}nwsL#?#B&dSV`VpM~M;QwXWPn>ip&5YsZ3G^`>173|1wxl{ZM`SokLDL<kQiek9
> zU(NcDV7;I+Iyp+=2r@x$yY)VQS-T-%isEyr)Vso~3c?#-Y&e^QGS~VkmTqMDilkf?
> zhMweXDl92JR@!RlTPh+%&D&e|tBAa0J)x*h_Rg814!C}gz0NPW&2o6GBYV@8d{Z07
> zfT@7%N@85IZZm?r3RIg<GJoZNzlf{yZYrIT$@GKI6WUBZ3EP;IvP!w+%KQU#qc&R3
> z{CPyY?i`UvUMcPfe6SqmQrwoU(kCVULGnb>ci6z<!-}#9TAR6=l*^P+W4VoKa1gj>
> zHAMqCJJBRGW^J!SJUjMQlImxw*6N1o|8mcByZq2F44G-`XYN{dhK(oVl1!ba@#=v8
> zRz($mTw;}niPve|_dVno_MB^Ftng8@9O|{WI-(bIxDjhn=R(BAYB8EXVt<*T*;2e9
> zAkJPja%F;3!^s-|dw6uO_4Yz9zkbU3NIj!xm)?@?^K%>$2D_&r%ve@qNl>_&b;P-z
> z4V%kayne7pi%Tr@7(}^3jRxKdDWk}~;AF(Hh*fb7H+O>}vW~mlt!tPFK#HIW@}BLT
> zJq-%bC725FN%d9Wq?u_aQRQR%Fg<{`{eWSf3{u%bHt`Yh>Wvod8yyenziRIp`SD&W
> zYYnZfeVs7(k|Lt2QXOL7x#(C*W%o2IMf=ni>Bx}-<3Swd)Vax6rDlt{qZJrFdmn2=
> zgBZK)j%_nJr+Gws#zh)D#z%AYm98a?@GTsut?R6E4$F&h(F9vKPqg#XG-*Eg3j+9J
> zP(G_@Ui$BOoTWX#ffA;m7a|HalYofRar}dEe5g%ikzCww>Mpq%_gUe6z4suk4fh9w
> zy>BfKoMo>pGcsX~Qtv4h_RCGCG3ub@iY(`M*;(V25)io`)l?#~sz0#_kxOC@FlP;g
> zp&+A*If1HUtS6cFR+fd54NI4uz2LG3Q?vm)$=Ihl9d7=q=`_mmVkz2nvH`B3i@%Ip
> zR@XsZatPQqBxf{4$ClGzFmg67TVqRZUFOa~MZ*wAy#(a9-lzo~>*k&iXwrLpwGD`X
> zXG|t$arGL{L}{nA9zj9fJiobW{!EN>hjT*2(d*Jc3-pjEtC+EO*|}gNzJ|oVuRxw<
> zr-4ui`0O<|U{G>e|DuaC*8izg0*uGWo5lTKlr5%fumAO@8v<d%cA}VUkMp%3Ciol?
> zVWG*V<%}XnopO{G*<sHHtemI=lzEb&mLzkPP0i_&I$7Z@TUCYs<J)%GkRxj@DM&ZE
> z@A7fLB~uP^(RrzLyL4Y2#;5hzE}R{lK_GCrX_rWLDyFkifX}v5(aJ#{-buMQ{}3BU
> zjAblRSU`ILTOoGTb@9UH()ZaHbL=-Lu82Oe+fK#Llg2Tn*6KHkeG@V9YTgao(GF1o
> zCx-UYruuwFR$!s6u2f1-7f2{&Slbs`xRN-ve7yZ1*kUhC^7{HGp_c?*a(ev%!<3^j
> zNecK{%&zq$>>*&qm7Cdu%-6CyVw%|{AIM%0R%T?TGtpPb`fv0Mz-7l(+K)~8G-EL*
> zmQ!rA5%Hx;@M!sB$#I@XCnfFN6f}R@JjV{>TSVKs>k%5I&EoSGS3Yy`xp)qY^8u=h
> zEUW6FhcXI=F+>saZQXZ(0bVJD8n|wZFoxq*Q}N7vg1g3M3(svgT?blsW9LXVw4*d{
> zy&5)$=aHhywfJ3O&%1{(?5@7pQ*h+zE1bS^3AhOHjCdTqahi{#4b?d9hi)EFPL|Cu
> z#Tp4%;BHHHR5^U-<`GmCwP+8nqq2DxEXIFWnT0oN5#G6)8E8^V(-QEm{<piO3K|n;
> zLEkWPa9gm`p#Zf8>S*-BcN>TeumMG+E6=w(AD+QZoTcGc)$WJCe%PlHLW;=1HfCr`
> z%jD}!>TGc%l7v4Xf)<Vxyx+R25hx-!2;3y`o?5xfz#gcxX<30uDPK9rb>omCD(N4C
> zkEj036^ybqcw*KIaM*)quEt7rg^yed9XzPb6dAHawUbTSh8L_>wHDK?n398{V|ZBY
> zSf^$O+x&J#NSS2Fniuot{-%BMiv_J%^Tw`mlA^Hs&KH-`eE2MOziRv<h;0!3M1n_n
> z3}j>Us43$;N399}38Z8yq%0BX;PXa_#~v8bYC&Aw^JDk^Me&g!o2Z>Mprx23S9b=f
> z&i5fEd&Pqk2{@5uWlr>>xH`1_*jJIG1&IrShJO6C{pIa40nB{tPwzXlE<e3@udUgb
> zU2BohVfvl#2%HGPXaiMqo<#F2ff^tC`=&>nI!j6Vl{~-?1DPWQ0Yo%J55v5B9^nG~
> z-@FqBaT>M<j8M8F68mNtGVddLSUPZ1kP@k;`rz<xF{zC8fOr+1VF@*4QE4+mVX#FN
> zmGY@H&`?8A6eb^m4B^oXR;E>?)<}QNUVcL=i|6i?k^|6A;XAbKN|Q;~w_hQ(HQf@t
> zxCN#09+gyJI5{exKuvy=_4uG<G@7R_!B~k2Ok6&v&zj$M*5|*L)9dTI(95q^iLLy{
> z^}mBeED88mwu@E}V0|gCm!g+WmD0rD#5f6iFy-;fkuyZcjs-=0Vxk9;6WLF_gj!bb
> zzw`2$t!axmQjGjf5@Np>RT^a@sQ>(IM}bdjGbg1`bQts4-k3K*VGJ^mR_<c`Fz)DG
> zstk|+GXwTYhe(R<pDxO-b=OgIq@AR*jt~ze9jWMC$1fRtYP`ncTHGb1VrdoTGvU3(
> zRN>x7mga+na;h^98(Cd834uEDuP+pQJo7QOUJ4}-LUA`0t2LjneT&)NyIL5UdpWD^
> z)|)$JBQa1>!~jO^ULoQjsF(NJjuFy=$Ve%gKgkotaHCj7Vuravw8P`0A{>@KSfC|<
> z0>LIYk!g7A!PMVPbzn4})h<S<VYitP#J0IAc15p7MH_`IhRlXVCLlKNOK|;1AM1u1
> z-CTLL-PfK2iEYf9b*<RBgfrQ!wq<3m6u26Wd||m8*`r(*!A5M#aG7)%1RH?SbW8oA
> z7nD*=%jm{jn5+AFgs$wSr8a^uTaq3%Mu~Zb+300}GBIEcB8Zj7p@{=yAM2vxFwO&V
> zg#auTvkwgMug;N^BdhOPMt?ZVk?9$_t(dn^%wWy%fZ&3dEYZxB<f7Y5_%VzWIRz*s
> z3qzu537#U={SpV75wIt5jg#ipmf#x2wpLYck2A9SlLzbvuZi57F{UnI4G%o|c5VOl
> zNr22<h?o1{z6xPXqC6el#`J^eq@d%a3`;)0^#N%d@J%qr_+X11F~_;@5Se<ONJAx!
> zeFiV*u{Bm=aR!&`S_dX`Z@6A+ci(fY@aU!$V+eClqQjtE)0R~CQsMnZnZS8bXYF}A
> zn6Cx-W$et+A2CO7gT(b}6vT=*3<u}=yAYtsh9e6IXMCA<%2w$MUUS$rK6swc*X-pt
> z>kboh3X>pyTFZM=)n<tNF?ONyfPV}Mhc--uuSXO}iz-GgtPlEkO*}*MrYnayOTX72
> z#wg_ZT{Y5OPm`i_NxpE)>+2WIUVi<=F7V6AcQ1NB?%-w3a_ehWj^w+cv+<#qsncrt
> zBMBP%s!I~X$1u#KCre&KD|s*`<1rI(tE(lV2<r@VF|F#VhGfD63S}a?<A*tkUd9+-
> z@Izt%8m?NqC}IgK*kj|_HiBBBO-@|sm_pEptBT4J$l8#hNbTkGFG5I&Hr|$zXxJA{
> z#8T_5O67>&?jz_K*}p4v?crslx8AkQ6^~MJfw(pB!i~fmu2!Xmv1z2c!~s9~KCUh@
> zpBq)CpNT5{fYA;h2Q#-Z*47z#*Z$Si+sn%AuDmbwGKIZUNww4*38C(eko3E32$KuK
> zH)Oqh)!>)USLu&};R6&0cP}B2={I5U0A?DZA;Tjs4kpM-+Rz$c3|5uVle@b>5+FRK
> z9?;GlU3|PGPjzY49VS*;M(zg~wT}2ui&q4}3Y(OiGzQpu#Vn+vrVNK-y@EhQ!Gz@A
> zji91t!~@?)o`BD&?CKlM8hf*#N?J0Tv0OELGtTn7(6$uG8ekjO)UeyFLw(FVE8`=u
> z85Rc<k5y+7-a9q6lz=xrDmH|G@l-ijhuHE0^GeLPhebu%geQ5R5u#d^UZuX$-Vo`q
> znU*emYs-xkuNWC{q2&whc&jCB%CUIt&q{t~<jITMhYV{>3@91MW2R6;@0xjv399*j
> zEZe|&QxQ2z^jyqk9=djkgjyW4_uZ07I!R`0+#oRLfg0q~rGl=h)HbR3|9;zN(f?JQ
> z^w3E;`FWhwbXle!<NX{qmF0FNrCWG9jLcq`*1Y8;3uaz4IXY$oL~#}^1B)&4-ZP>(
> ztI0;@QJ(9`?kw|>b9=d3<`hP+v>BMG%@^FB?h!S$LgHM%ZFL?l^^W6gd)U%|&Untn
> zjPE`P)U4RmFPqs04C|$9{;$517~Md$(3;(YJyV_ftJ?fcz8=Eg4y3Qb<p{T}3-iqm
> zG#xvy7U-NTyh}O8S*ARR0S>-RC%GMsTjPC!$B|QFIjG>Sv%&A3B9e~DlV{S-Ye~Jn
> zehG8z=avk8>xw(h(0zArjnXY-xx0|rPEu5U_l~-ubku3MLzkt7i7t9gjWMD$JdOLx
> zQJfujFNl2u9*nW3GQ0{n^kql*1H$<iS=UBfVdL;<liprEr*Y%vVaesR?(WTLB4kdx
> ztK}Bz;kf^yhYDYIt$aMHk5<5K&}6kaXHlNbTgx~kn|GZJ6q$#N-3ztKl+%EY=}%(m
> z(~+IBi0oSI=8*`v*Ci2N57Ka2B%d12*Bsp!Pf8(&V~!;9j+*CI#&dIj9?l)s6(+-)
> z+ps3xbPRPF85ZTIf;VnGOa_o33GN?$4|0ng*(?AORSU9i9zo<r_VZ~mxk4ehYpw+p
> z<lXhc;fq?8MY7A7qHDiXs!vFdR5(u1@8U#z0imcv(+NdbZ-W;Znjr#caQIx?k!)V_
> zy2!rVeF&ptpJit4mz6m^^ul36HEckH0^4FtWL@>enV#<ljQpLg-c=+eYw1>pSiWxX
> ziZvty-LQv+7Cp}P5iV416k{C7(hsVb<x3`GG0BY~pClBN)QRnhS&FB`=q**BbY3kG
> zdsv$Qt<R?H8XXSVBr~QcxSFH&=-qt-23av5zqm`(Pcz#IuX$?<$u)0uX7b*O2g_=$
> z+?DK_2HU2$B7YAnWz}7nN1Qb)pvf%MICd}`Kr~t26&uvz?pTBwmjP*WzS0>Suyka@
> zgVbaamlfh<AFvl=A6X2Po{>%Ct2VQX5Yp7!rGD1({i^;1L%qL$dKdqR`3<g%)ktx#
> z$UasFB;%IYWKx{ZGC}SK5B?PMl_+F!cEVuYGyZHtqoh>i#C;*Rm-V^7a!DEa!ZiYg
> z;(cCqPiV#~BQz8UQkJ<|wa0;Z7cAps`b{O6jq^Egu1>^b?#B3)7RJ}x+;+N8xAfIV
> z;BE6%#KkC=sd`l0yBTa$<dx|b2ZVX*ta}%RVFS=T^oIYnjq^W8jT^qKT#kWN&*m*$
> zvacpT0GlUCFQ*8;FeWKS-RU?8M=@qA*(_8%MI5WRtI%>P3M<RQcyq`zY##PtjZ?&?
> zfxWG>ohKOP1z=uZzYM+bFT3JCLNd90q-90Cco(P|mw7HZ*~YSjTU5qzSp-Yo%D<zb
> za&|?|sbNu!MYiiO&m2$gqoBd8UVwWUiyPP&xCLtad6^QMJ!mkLv`ko+J~V2>o@%`z
> zA4eGip`*SfK6Obd_G*60Qrzs?07m;cSUti_=p*k$!_2i9FJ!JET*AQ0&6MTWp}vs3
> z_8o3x{qEG~Xn4zws&^X}>7;1azvd3;-L>#cC7-?snoRa$0X3P9!sw%eDo5lT(b?EB
> z0J2wRwgnC|C^%Selhqty)M#1SuuP556_X+pqcWj_toK=VcaVIBb|1~UeiT$571@0K
> zV2_3hd)DGO*C_gzrLX(R&IkYfy#x0smq|oNH+7Q@9Ei%>K&h`-`8kyR2pX~mx!hxJ
> zyK91M_QJ@pFDdH=(Au4F3C;>S@3AN(NtkilRy<EP9gaC&4)gie@KZbWY(0LbENTi1
> z!`6Ae%1-4b1uK2Mo7FE`&bb<%KR~T!JD2>VVMv13e-;acBd1Pt3F9H{7S}C&Y;D4W
> z3Jg{B1QWJ94DkX`C|mW@jADq609WMT)Vi`htM~6?zlfn}Foo2?z!dYt(tgIpDLTc=
> z=+tUla0sa~s^m7ciJ774k>PBNf&hD}CH=ZG02kmatHMy_poO;-4CoBHC_IpUM354-
> zw9tsEkebMW1*dfW{`+o=)51e_<`e6=JJ`ThGfZJ+Z|JId-SX*1xss;AUfPeJHgV6>
> zDGi1#fG$Wi9ZSZ>VF%CN-Wo@ud`-5C!7&3)=_B|sUIkjZ<I-84?9@4P0*R9E)}e1l
> zi9C&)f~vn5NC2%L5d31DUmCq_mYAx@tztSSjjc=T;^$#%IfTH@!_q1`4geg++6^ne
> zZr3Sc<-olf`@f!uu%<BlUp<zzK|dp7%w3HZg5X^?pC6L78`q&3W>|s*Wd283=)acn
> z@h7QnIjj5lm<Zu(6=cE)@Ns3|;Xr&8`Etsl@bIGivtsH=&M<<PuFQZrXL>en%d#aF
> zu!|4PNAQiCj+Ma?0XNx6mv$kM-_ic@#KG6se=2(6@-u#W55K@JWij3YMcGfT;wzP+
> z)|6^dc;vwDZuCiZ-_^kHb{IrrHSZjGBZqp$Qv%Bhb9Nq4+;38%rMYvS*_oaUMV#E~
> z6E0#6+S8_NBq~_F0*%3O_PYK$_>epkoj<(oP}YYmIG67Wx16M?#%i-!$0s>nMmmBy
> zbk`R9h&`rwI*F&Pt6$b|<7N&O#%{oakbVt6Q??r2xiW4G+l_~l#exUD)6Q$;;y5aK
> z7T1HO1#G3BWVrchS6eg1EM`ZR<?*2Bv6n-al%l<w+__z;ZzcHVsUY=8N7*|@2U2Ez
> zz00d#d(DqAOXBL@!?xM$SU@Q5NL@6XiG>N4xi@spix&RW!SlK65XP;U2VN4>KWfyn
> zTc1{h$a#!f&L)I4fZys4kCjlVN1zx99+f5d&9yGa7@xz)|J_}ytR*bbvdHvdNDMk^
> z+{qS`lbj=pGH+Lceiw4lERn6*UymVZ>IiHDvHzdFchQm?Nv;IV9EePkEwyyc?*D(|
> zuDYw3nE|*B+^)SGh-9&)9;v7kF|8Uh85x16!>-wV;JBG>;Mjl`WpU^$aIG#S>`#kn
> zaNY(L=k8h>CF%^P>DJAHIcjV48fDiwng-oA?w^9xeZOFW962@?2s66a((V0Y3&BiN
> zQFX5p5vCZJaLit?Mr}UVb*o}M5;}<q&*(5?sE&N@6s%Wo=&B`#REAruv{gsMyMlu|
> zV7(VU7`eRPclV$h*alk#EuW25eRqatsYmLoxlQ1PUG+NKx~+TRe#SajTU4O`P3?n^
> zt@=$<R)^*HeXK&R-*{kH9D!L~3fI)CI&LNDxWOyFux`Nbv|4<!%g>dKWNJ>&`~s`n
> zDt`u8qCy?bFCG<JbAP#UZ?eu<R(@5?20)89U=Aq)7dvA>hq2hlNQ-LCox$RSV)ei?
> z@i>4;@Wg3S15B<e1=!@`$$L}xb4>3w`)9<(;4!eSZP%ID@q~dq3ESWNj<C*)al)zi
> z2>$o>%b8dnR58C?{X1v2Oy27!`_PaLpXPzr58_$<6(t9IuY}8F2E_SfOBViundP|8
> zN1Kz5^)cc7R?nR@G6<q+#rt}ko=icZ7mrvHE)%3DetEwBA@m|Ym+(4c94j@;_#Q^!
> zc3)`_7k4%V^SGEdTklp?g5l{EB+n%};mv7LV`j1#)!Raj(xy`~o7JMq!)&L|`Ze^P
> zdz8rjr02r*Y~k9$^T^etFGe&9+JH5;yIfa}z(!#ZWO~*a{6%zHrExRU$spLnJ=mWd
> z<^i=^?WI8+P+9o6WMZ}qn!71MRfj1tT0uupEs`O4=ywmmc3<N#t1)a!$~@^MdRZn<
> zgyd8Nm16H1cs~m9{lVl;E{CsbW9oQJGAcg&tP6`nCaXH}{47$(&)rMyIK${-`YOz&
> zI&qw=yDbcBAcHSqVN5Qszbz&V1~E)^{5bn=3S<u5ZS`s3rrfZjN+b7D3rFVQ-o(>K
> zA0euz7V~9l3kUxSV~}?(_=1x*_DIQZy~O#Y^3r$$4r9^`Elae`)De3<zhS)^Ku$*@
> z1Jknch-CNseQB2M+MG5?#Xw2B#pB`ku?dWf1M%XTU;Ha>K51n48rEEtk&Gi3b5W0k
> zFV_PULA&4Str~bN<owBPM^5>qn`_BwBoEsmcy<A|?7sN8Oh~$u%`l+D%?NQ$UqWXO
> zPMy#+bul&F=HBO<35S+w2b`cw#VxU16jSn$w@G+3Z|bV|`}_7j`V{*hgcJ%N1~2$v
> zn6}5qmuo|Pevj?+>&=9DWZrSOU|#f4nt|TOxF}w3%gbWU)VL8eb$%R_qwGGm=eM`}
> z-`|FE13i@8EhxzCAF1Seg}wgixrKU*6U>ZL5>Z`7eUvPrVg+toTtEso6Avw|L4H&`
> zMM42pmu_Tw?s~`F8Qte`gumQwm^!XXOpF%Zh?muy%a$FzV!aJ9kfgb*E0TdhANo+3
> zx^RT&q(;95X%;^0=vcipv)k4n9rcwWgI;TM;HRS@h1^nU*sBlvuqyUq2|)k7gt3Ps
> z82)wXWc3j!6WOay`PiNBsQB(Y-rH$(n8l2c`O0ru=ZOD{i|Bl?qVWQ(bkl@M!QJIR
> zB5AagH2=G0QAk*-SO>N~fW6)D&~QMW^8M%QCz)gNkKSzLOijt_F__#IN*7Kw&FX$p
> zdex>1g;DgdJrATfe;dQni<mwH=$2;i5(eW=CyV}K_sn>(er>9-ThG2}W7$AR>28F-
> zu&;U#Zlt)ob`t^PVW!duc=1O&jwh3i)~L|KGRe4EmIa5$fK#o~3%Zg=LD7NW5}Y0c
> zP%=?)rqw31f9w*Tp{{<h_HcBmBQ-o3@G8qb4$<96Wj!DV4tsJb`eZndI^P_P{U=H&
> zvB|*6#4$uB^4SGdE`#YgB-bP_zCO*06Zh0K4Ochv<3C#!ofR@6fv}irmRh(JildwV
> zN{?n0-uALW7^!h}E#l|)uxPRdwnLXt=bLLBo+XZ`_D*3^d|Xs7I*SOOQ?*FmwOzfF
> ztCCE@F<i40!%(5-C&$S+oOT4f5uiCjTt=OEXu*;p4sQy1$9%H;BTbv?c*u<-*DV%i
> z+{in?dAHn8vYQBOC3oRqFojT%0nXJ&CY+I)YsOFovK99X8`((VL~KqW9p!8dmGQ{h
> z(U$U^x}GxFK)0G{Yhp9aNYVq0QKnr{U55jeI^$!mEUUYkx#{%9B?O>P6hdT-O+sfS
> zp3XD^Y8R^;;`%PBEF4}ViMSdne*Afy3WUSp);^%Z@jsNmN{So7tcGod_4+88`>GNV
> z3{rH6q>MqsZ}8@B?isLZL5z`32&mwutrMH$sEuLQ*O$SS!gU+rn;#0L{`UR;yQZxE
> zcEBpl$nsB<;O0p;swn$?J_+UNRLe=qBExB+UItZM5OZDjLodNq&VbY!{Dq4!B5Qh2
> z544J5*znu<umeJDZJdbLaSb;lERBdQmDeA89S;!8+A`6Xh$kI?dnMQ|AOHOrbU*nB
> z&62|~ED<`Hw?`qOIS}_0x6JC@0k9%9VHWK{?S|Ocr;~#sJmPGiSK3><UH?B-K>Sna
> zUi^d4{a?W+GkVy$)Ji3P(!1o37&O->V+@i#3e8x;d82r5SMQYO3X~vOM1rt;KThjv
> z5YD42i=`L?A1TpE^eCY2I(GUmVwnF;B*Q0q`LFf}vOq7H8}V1-6gr4I4oi2=lr6HV
> zRnRfQT?rM|^dif;R<?lBBsxHd*?Nv5N42xZ>a2=SHH-9u40uL)3(Zr;@n{*O`0-bn
> zX-mbHECe=i4hUDSNGFF&rWE1_dT!n0hs)d`tc_bV{AzfGtJ_oP4-u^+94}(H2I*KI
> z#_DXXQN)Yj(adB1AQK_<@Fqk~qPFn@>`_Uw7gw3XhX4<%DBNp1Q|9=cAbyW;jIOZc
> z!a9f(5_76)>FBdha%TICwelpA;Ta@H`=|`f3$XFNQC+nsqc+pJ7*=GB)8sw8wu<jr
> zSTIMiZh45*E6q%aDXRDIvA{@oSsN9ouz@}_ddUmg>XwbIDcp-b2FAsVVhC|A_J-yT
> z)T8LUwf5y@{d!xzyeufSwMD%nyd3E|q2!FHB6~17)3VyXMu8q`(Xf;WwC0}U#xV=m
> zZ2US#i%G?Vm<q>1FFY2Lu<xL#HH$Aa5Ig>9Ul0oe(*-4tg5QX{^sc`PiPx%*-s~AQ
> zHx)hOP=xK+vUh~jgV+B`6TOGrdjNM(z!WY$cti(cZnUdjq?x;#mu{tn(F<35pp-_f
> zO_%rTVbxB`(p5_#<!w26RM^BOxKc2|<0(VSJpDX%ik)DYCO<>Tpbdo;;-zkL({R2T
> zb+bCZ4gC-E0K*PHTAA|zJHV<NTZn<lhfdp$Lj;GnN)ufq<>{)wGKt**U0^JBvtUqW
> zudNT@{oC8{7W@0aE#n%7CT9!i(u*kBd@1c=)4g*Rq<J|%sxmY(+H96?NmFj?)uo+1
> zi>#bac5}*U{$DKJjjP$6%uL~zkXbYXF|zqX0^N<#N_Y@}3AX!T2N>RWGY(mrT@OgH
> z#O1Lmynuwv>;ze;hX0x^^_X<Ms=#K^m=^`=_FxTjZPAD9Mm1qM{~ImB@MHK%tpfiu
> z#v**BNCj(zi=63KAHST%_Z59m&G)^Snue@@>H}Jq5f-aHf1?dEC$6=pFJP4uH-zN4
> zAN_Wb>7>lod_7dN3A(f@ktv-<K0_@uXK(zl=l%nT^29Aq^z!4|tp=ckXSrv7mCGyh
> zAMs@J`GE4i#$~H3I}n4wP&nGj&?;E`SxKz>=;qEuS{}XVy|*qIngIY4`3B)PN|SZQ
> zbc2}Lz1O~i_-<#}G#@3|?B1*Uh;qXt!QIBV7@JbzVmZly$HOTsStGp!RrQ#h1g}XS
> zyRD%p8RiBb>P*$wc3Y2HVL(ButS6xoo?}&x&sD54s6zQ_X^^-eVpafyKzzSyPmw17
> zF0Ly~XrO3vbWc%GUGky_qlHPQM3VS{O>(>y4Xuvbo|KLhXALfVqVSdZjmD=qjFDjP
> zKr=#f@LV%LvHWXzMk7Mr;x&~Cb5mWlg9Oy#s#Dw{P*(TYy(@EuN6TLU=O`nzK>9$L
> zt~>TcV=vOzVT=z3&ExCK`Y*5Rzka=e((|E{vNttl`punEZzHOl&~Rl-;{>8eFxGqq
> z$dkS~eKoixJX=icZYMdsQ?1S4C|r`ApJo<blD^)1D2#)8x44@h5A--VeR@+LD9*6A
> zmYr!^H@HuPloExwqsK6qEyo8Rmpzwu_*f9uj_$IJWe{?LPRCKE-&*ZeH_wMHdy&Dc
> zaUFs0WWhcipJs=5uT6m(p{UHgb-7kx?Ed2v>X&en2i^~ESX)w=gK-lxR7TSPFxsDs
> z>%7&XP#ZC<9@*WDMn<e^v$MDA7Od)1jNgj^qmQ!9im>(?R%v~NZxYV3S{?dhW)#HM
> z2nYt?x7QU`W|2p^d-Uq}_w8?Q_rJYu05E}eyq3>WEM1PV6dTDtmlU2ywI^?vY$}_7
> zf6l|R8mt8(Wx~`pTUj38e=p7rk#{6+y-2f_b6k7aweKTE>i*?rId13U!c^NpcP7v=
> zI8^vJ0G7`)ly74hfg!T{Sz8VaqA;7Gb%LMxvElGy!Bzdb!qQE}Hi|(Py>$_=GiZ~x
> zzz%xC`!=L^@9OBV8UM$wt~YIwbk8I1UY*KM;1>QVa{51je~h;r#k%~GS%>^^PI9We
> zxsc-I@vj%^>@?hnPw9`22Nx|${2(lqB)l0}>KLdQZ6xjfWWM{l)JVKZH`_^0L#5LR
> zJ)gXXxP){2KLI|^sml|+{0xARa|1wP{xXGvS@>iNXFz?dqD*LhUv}sscDp@xvcC9+
> z<~R6ei<}b5gNuCAMy$s^P`1h2QT-gtcUJH*cEF!2x)7u7*wmhtsm~^*G=D0q0^2Fs
> zTK43sojh9~bOV%5+7*qQxYQ}(Fw%rgQ^w7IJW*C^cQbq@L`=Tk(C_A8K6{{{)XbJd
> zFRrmc6A=bkp-!pY87aW-9D^`j3T3?tBj<Uok;|IGGu}u#JB1a5)GeuNw}LwINssVl
> zqiXP+%&s`lCy0rgnI@FS9_F0|6A1J;MZ<?`ck^rg_ybNr`hrqMx<qCUzB(de=te44
> z(t>+6Sw(|4k=7$iGe07TbaC)sc~l-px%1brBZa+da=G&658Sf<KHQlG--g`j+Z)3s
> zQ0eE{S0ca=tT%datz!7oy;4c}uS6vsciGgCj<{7D<8-Is^oU4m=2AVZur#v;j!W*n
> zhI0`qM(i3CXDh)fz=EO&-e81aG+Nttb!S@L-YuNXMj^h+mxy~D$xGw^ds$5j4<=r7
> zH`rDkH97*&wR~4|110_UWUG3->?q$I5u4DNoNXBVxPbO*sNG7I?m%A~AuBUr^UVhu
> z)mob9Oj4?gOt2sQ^pRhX`r#`tkmcyr>p48+^gp;(poZ=dW<rD1B)eDb!D(?qk%v2=
> z?$HQ&wW3akEA_uRu3mTs><4uD{e6EQ{>a;LNr!`+6s!DZhn-^um|R`M^0+K9p_k*S
> z9Wm)!!v7$=p7YX`>vUM+0ah0_jI*fD-{Rh3u4erpzG24xruz8ivsTQ#E#p|>rGp>2
> zEjnc#_~cmj8BTPfXymq-(PB~AajdBL5DZq1Hyn$`v3h*DHQ0*<bT{gn(#4KH+&6I8
> z47$V|9!JK9^Zh|v{qvwoJ~4X#vs9ln5}jr&Je{L+<kBxvx$=cMW?`s>LEys3&-Ut6
> zUj%Vg{*X#D-8j)pbdoq<nBSkA$r9;0vn}RNJ`a`Tf@$R^rYG{V)#($%JkiS^Un2E3
> zV6Kp*%w&}Jvlq)s_BZY4<qg>g5{xo!#D;MtRfi%|#_R0^;qtYXMQa8rUENYI3@w0p
> z5|4lJB!r`?fY?!sEr|zVba{itk%4+776QYkS;f>^DD8YRa;4(n-b-&{SI6Wwt1{4B
> z#||FPn8hP6J&+EB7St|QRH33>v{V9OfkM~$b&TBcz4vKk;V%By)7{JCfq&Qv5?9Lf
> zXq`U7Fh5w2D;aDu{~_)@$YfbL(aaVr@r8wV;Mb@Q{UkW+mqN%+!Thf}6{MI&C|+FY
> z=DCj_uDFP(_^5G@vfy<zN3&yz)~OxL#Wr$PO)botM&+uskgqQbB+feSXdm0ID(5>?
> z&YsI|#kT>yPG*}?MlL7Fx!V+UI1V=^KXQQ69d;Lm6_eMYUgy#>wa45qB2q&yvt~|c
> zKH6~F$!=m8FYB=jv0<(Sw{xe%Re^1^2DT3tQzz3D;S*GTq&{6kC#^Z2Y$aMO6gbWU
> z_-SDW?5dI^^Tr6w8b{{CDNK5HtjB`ZByOeffYN&<2Rl#-X(lGzr3ctP_6g*%GV+wh
> zQ+C|Ca9M3y#7BnYZ!v?iel6mu5YWjyiz(#qLv(RlP&Ds;N0@+$$+?k|o<f%7BQcKF
> zz*eL6t=g(Tpt#vdkA6RSEVueD=*GO<8pcq7F5gw(@~-joe}CV;zne31k8;>Aq+T!7
> zlG$aWEn&LW&3x`>_ddDm`?%Yj)~D19p&GYWSvTOSNfCJDVlW$BN|3cY?I(T$TX0PF
> zpmhNxaKdxPg8VjoQ(*a}XIW9Scf&jU++J^Xe+7N(xb9Z(1=$Z3c(1F)>3kjb%ti`W
> zTJQoAYaQDI>Ct`A3wLZ@Bs*i?vID)G+C%cG(=A_VPoEftogW^Tp+q$A?XRbKzs#P&
> zzk038C6OM~kNIF^@ibTSKM7j?fuio`k;BO<>5q1<40;~?LKX({&)Jvf>xo`|vX3CM
> z6ej<%8?Nw}wkR>Bh`%gJAbF9{g72UQV5SlFlu>DgTR+Fs#@s5aCcAN#GQk33pV8}o
> zkH?01!i+uJijj-e5TR+Y_1)9uMxoHG$9b_nvnOHmG?ufZ-PFdeZ;PxO0+Y_1rh^n@
> z`5&d{+C4|CM#n^+Nj{rp()b>q`L6N_saoTcCusSr`~a?SCBYJ()>aB);VDNrtsPGv
> z%jMFThRc;h!a-njOdFPHmsz{aB|H~rXU=#>s?T-ewB)ZTHyE+wh-sxhigi@9aMMP6
> zRqGN(wjc7cjzfHt!9hCegF$3h4_Pq2$dZD_t{f#@@TL|R2D`LI)b92u{{H{p2Xs+C
> zqI|l+aVh+!8yRa0GOFgZCF1mN2pF@wpBS6fUa?(jY3g-KC?c=VdL{-6<~f*7K>Bh*
> zCP}!m#75&m#YL+h*wal*9RbJ*RO$udC&UF~n|c)Ps?hK_PQ4yX$6%mqd|n%YFn4Et
> zYp&ujZHHA_x8O)K(Q;7HJr^iLih56@r_Dy5UK4}6wVP2}cyqagMx1>%+A7py#bZ#^
> zY_;L@<kt25lfgQW%xOLrS)Xv`u;HH?d6yxxjkB8PnNm&9bYhjdd#9B%9O2AuoGsTy
> ziuxc-M>H_Umb&-%u9s_nyKld}?;rR5_rZJIw%xBEvu3sLWiM@zePrP+%}W}O|1uFv
> zE;dqEp6F!lHFl;L02?3I=SwxbGVYF|67+SI-O<EdH|s(dhPLbpOWf@8gIrULNQM|z
> zwM|!l2_$ZH%;dQtkjKZ5><tla<`|JJlH=nw-G$!OavB^$rJF8b1}<%yKXc8^R6d&;
> zRS)xzV*`%w#YwT@e3$ZvBmzY+mi%mC@PHb`bj~(8!I*-8_#y`>b}#av@Bb$UGN%zA
> zGk;ETDTjm|yb;yoDgUFpD*vf>o<^zXe|=W&&)0t&da1V*U-7gh6sFuOXhLd7)?LIP
> zoZRt=M8qDn9x3TT_Q6*!g|bv@_lP+&=(40n8GHulR*$D7s1CyhceT~Mg<Grk&ti$e
> zY#oL?i&i`K81_`U3Y?6KvP1`t92ce66H!{8rAKhdXoFi(^W&ynyHPrPc&4FMb6IDz
> zGRm|pjtF+L&=pL#7HaQm!I|>Qsy|Jo-2;sspRvdFx%1#Xr{(Iw8>Y|E{c_hJ>{;_j
> zIGZ#0X+2MJIH|zmiR1GG#{I_<3k&lpE{v*r70pYRBBU{wmE+QPOVo)p5+h)kW!!E9
> zx<S=j)Cc+AzqizOdn0yOLN(+_=;?-21tMs)$x46we*cf}cb%A(N449BO%H%#!D;>A
> zljw!cSwn2rapDKo%DE`xqPD}XX)sRy>pWo0+A)5T-T?l_#ZN>Jo()iIOCFA;I;sKs
> zn2YMT#f*Igh6eySN_+~fDK!`tqe9li@g~Tla*klr5zSo*Z0q8tpS%0gDk8Zx4)5kG
> z8&k~;6-{rGa6jg>alwQ>CkM!q2fvk^U2@0vg=f2PC+Y3lbPpT|tB)w1p=!giuHkem
> zb1ls|r-)JFLt<po7o8Po%B^0vCd$XqjA{^s@WL)Kw4I3Hn&S_@jWNsU?tecD<lR_O
> zTB*~l3?$c)n>R=1O~PZ1l5oGU6><?A92Z*HJW_f8E&<h~1G+*b)TO54`k<0i^h_M-
> zvEEaQXA=jXG8VC3(nw)G88^ZJFq?ZtBKpau{Vw_<GnpN9v5^hBE9_i6-$^{eviFSE
> z8Nd5Brn@_qmoG2tzkFHYk?^v#2n4jIh9=LzK>vW0zrT-UQkZDN^DQNv?u8SWIWC@Q
> zQ1!#X3x8IQ&-f&VDgk1PJ&I7qKQm7=NBMObLOju{c+$A!Ly$jtYW~;NME~P}=Lu1s
> zuRjHPkw>$?D~TvE4pVKI6lV-NnTG^H1pU^W6wd;iPV%7N;)`uoY<rYMX8g4^X&dC!
> z`IJJZuepT!s9l6O_|oc5T>SM1r-flcMXu^bmoDP-pv8<lhj_B$!4QL&>zakSq0Cr}
> z?xnFg_PBzUz&tTsOKKI;(8p+*G%%tv=oTx&(B2DaCRYN4zxt&EL^EfFXpXm^bbt>m
> zM6LrCDnq&Y*`+yW47xUxLzo|^6`3aVn}6j=9uUU6Ie$RUJ8D56TA({y)!|f3c;MeK
> zN-;G;1wlM$guRTslp(`=6VS{&>w}<areeFSymgI@W4<dT@~HMAlOC<&kOfPz{+E(-
> z8a}Y4sjOXFBr7tScwSo<bJ)fdrpa(y?zlIbxV@DGGKY4b+(VfPl^KvGMyYD(X9c%e
> z^zKHZa;>)1nOICpn<plPmp9A+Moyv|YN0dRGN;9M<aql{i(16-sTbC;F??CmGRp+?
> zA^*^=Kru&d57j(9u=!Di^+E)&#z3{ZrwBG%gE3(`Y~ZI^1ZS~+mS!eqlF_Bg-LV5J
> zy8eVvO~ibtRA`q;_M6LfR14w5pa^iZX|s)v%b>=DF#%mnHNiO|8`fkmjXllX_(PKR
> z^seL%!$x`^iAJL{q9yYF{e4qIEej^voN;G^^RZ@{gd;9I>#8dk*AkYb^gwX>^qyX_
> zE}s<4;>Om@VG=uavfbM&?-8Hl2Zbrs;nQ?jlA)TjPNGu_J=gG&R>=u>d${CFK%G5j
> zZXAD(>k1Rr7ZbhY#(;`R8oq>;{M*a&Z(nb(w?)i0z!sS*$b{kY-@f19?*mUB|Fx)M
> zAG3rN4fu!U2uz+=e=t=jsQ_{TE8<9uxZsmAh~RRf&9c<f=A9KxeNF=SRhVOZt&>U#
> zG#%<-7F-oFdiR`l^Uv4w^+YfKba;KzJn-jtTO^277MfZO8Nob#dQWtIDGw1Tjddz&
> zTJjn$8|ujkhKx138cLv7ud~e(Hb4StI?AsSPczCCTVTCJu&2f9j;O~s-#4PtK#iPc
> z6I;(R^i$ElyV?VKU){^24q)hs$6m;Yr&x)j9X=jHyS%EU|I)2~I-W`22LXLg08v5J
> zN&mqQWG+UWn#c4k7fnlMn&t;IAN+TFW@RLczcZ#KM!M^i2ELJzdR65{(iU2DUCuxy
> z>UDO`%&IDRu(`rkE7&!9j`S{SZ7E^rEfG;(w0n<Vk#H=PGDli1Ev~84vHjwQ_nvVP
> zLbH@c6ihG2o9{bf=@Etg?REL~y1w1RTD6!a&DrEpNmEIcMIjhmnrf!3&TeUIk?b%}
> zk*}_C`s}nRA{V9}-p?E~$cb-eKL_sG=TeWQ;ui848N=X>H;;lDeQ4@E?y@qgBrn{D
> zQifz>v&YZ@De2he0E7)-hMYQRFv+4_B{BpnWiHItn@VeL%KGyVpOMjqX=?9jIS_(0
> z1PC5i+Kc|;7j37TU;J@WmZU6J?qc`MrOne+ApX`C20lM5um-N!Bm%i9f~p|G0dxs8
> zsKh2!N=S~sf;JX9nd5M|DM)0Vx)p@jR|A&pJtInx2?JB_@n<#13nN4?vu&mk=emd0
> zZ_hmY?yF3t3+pi4gLIiI7^|dT40AxXS(tk1%hbeiDcl?JD~MxsAazvb4A{&gPi|{%
> zndIO_uW9r$e69s_3dm>Sm^cD=izpr6KirKMj^-EsFfN;=?a-w-!tv{2P}GhU=3l<7
> z$BB!)(c{Noik}UL18;-5H%4I}mYl10)q4-yNo1#XgB@pGg8UH`%6x9FYLsAsNiO^B
> z6bueJQ5i)VfMk348h$aOf9XHu8~qwJ{rSN<dlJwE*zlx=|FuUj&)4(y=R_}mIHEb-
> zz^8lg-0ulSGEY9oQl3NojDL!MR|#xlPb@)avwJ&vJQTMvnuvm9ba^qQ(Re02jly?0
> zYPC~Ge`GuC`-t82=W8pP&f7}Px0xn0A$SqzN5x_l+G}!NN1GHcsIXxW#ILMeXZSez
> z18kTt-K<8B+5+>LMGstehSscj`E;gM75yBcH%0f)JQ<fx@ilx|rg<vDgUZ|sp*j40
> zQh6__$L%5R?>YUc$u`bWp;Gf8yMx2jHO@uztUxW}vg$c8$H1b=gnRwNea~GEf+EU6
> z6T|HLKFd64PE^3J+*W?=qrU!nTde>hfi)0mN_yy+!*VBhbQGLJ7~pDXo#5a!3Z`Xf
> zRALUJ!vqfRvU-^bO`fp9q1qktDTbkI7-+JmTzFHtWR-}8^D<c&J1lJ7ekjGkc2~pn
> zqlg(X7wR)$qI13Y2WROhTLsP*rXN5<;a%xu+n)1aM8QycJ?DNzBcO`e;AS=g<5g%M
> zs1=LDrc=@8Ls7j&w#B9{Lz8`fSs_bM(=$z9X&eshuH4VM26b&SqjqSuF?_I67)^X&
> zm6q@oY%2pWdSK1)8S)#8T<lbafe5P85BDK0<bU@)OsGU1w+6WmaV3$5i`bU;&D#0z
> zs&CmeB?irbR5%jXl|lVca061Te#eGkc-7K=BMF@KLQ2`&Qe*GAI+%rVSwvY@OK4NU
> zVIAZQ>1_*|Sr)6>J&hMdBj7X@pV^X(WfLvEJ^=GZr%6G0HZNY57Rj5i7jGlfascCI
> ziI$@0vElaIeUur**M|HaZP0ufkx;8%u0!_)xQHPqPU1Ga0fx}!u3?udoYQ#Ft?!cB
> zp0Gv!;bZ#(T}rZh^DdHgwJd2T>3KA#?zEPq-NwXc$2iuw8@7NlFt>ZoTT(V7e^hMz
> zNd_-JE|V@omP%Ji%p;Ro#S_CkUr+S%-*f{{bTWB#bC+8*h@m{+zf>(cWR^`-{3H30
> zllc>DgyKkMH~*#4%Ve7BOFTk?R#d6KF~EuUYZ%43gcZpl0DJX(Td0bjPr?{-XHt{i
> zs@somkA359K~x}PScL7-=(>1jk6%G3J4}9ziVX`?PrKuyr8_04T#ofLRbvm+jr0(q
> z2hJ$oyp(w)W1`Fq;xyKQ^~HPnq*hFU7MH#-)U5PaZ3UyDrlq^j+{W}xYZtz&R~1-8
> zC?Hl>C3KT4o2aSU&5>)OLcpL*b%~K$h*09<8Eg$}QH!KAY^5F*xyInRx8VlN6c)_*
> zmeDKy*nS&SoE{z)HKh3j-DC5}*)pm$Q~p@<9=IBmkKLh({a<T$<|zWNnnU=BFi<;Y
> zD!X0zp2SKf*%I^p3y2s#SDGWv;fd^<TJdByYJ=5DfuK5t12{sZRU~by<wYzn2uZTX
> zzrN|m#XOVw9Pk`R@z{l<u(kllBB?+A`}JkL-%OOh?>2v!9Xs~5I)>?Y9~awTrtKrc
> z2OS6UAXhk*jiaPFSa6b#XeKo>wm9~c2I2`NSP=Q@#V<u>?Yu|Ka{`1Uzp)qE;R%02
> zBY_zUVtKHJs7sakQ$g*mZyR&nJ9HG|hh1{cpvt|lH6t@kiLYkQc=8?%?m;TuDhj<~
> ztflrtPbG>R&pq@fdY#yy%TKYn@GD@Dd2Z0y=ZCgR`&h+-ZYGja^#u;)VMb@+ESOk@
> zz?{V7For5G>oRC>1Fi^o!mqbsmpr~*t=#HT3N6+G4++mM)!?aIj@<l!%o|`VeHKiq
> zOUJHH0ReQu`WDR1yoTir0zS(`=NY#|mj_e6U3snz-WwF7GtO>Efh+7exu?hhOkFlN
> zIS851`Pua6F5>xf1d}R6c{q}JL|2htW3QjD=j(qJdO7Q1e&XM_1in`)6YR^v%WT$v
> z+XFJ|IrNwd3E@Ob*p*`3J-$s!OuIijCUnF!DHbR*0aH0cvnf-1<Svpzg5dCwZ9^9B
> z{zzCTrNB!eG+S3yJQLcb)#y~YXTSL4f5a)Gtn6wD+klr^qDpb$ugtRhPc4rN1>8f#
> z9xGmY^;am~J!Xn3Qy0H|rdo7ac`#e(l-PCMG_xXzX$(k!^nULu31A>Vq=w(TVvb}>
> ztGY~<fWD@2*%5nRV@Vsl^18=6NH8%dd=e6Uan7t3j)Xgcndx8d>$lex7<IVKzK#D?
> z{a5W&%I7L0yADN62jBB(_zgm#J|5K}XZJlC=P0=%J7~Iw-GzcnhD?B#=!OFkxp*wA
> zJ-9rV@lhHKM9ZLilnr2$IrggAS^z4o??L)kn}o&uyG$6iWDnk>MeTA06%TBjVnZjq
> zam52z1XdmUd{K3E@%YMKhFt?Lo6+>qF__yHf#mEcBLCWNuj>MgXGUJT2UE5Yu@Z~T
> z+6L(jP*y>mf*GFDqUxotd92+Rism5JW>(_tptv$|_9Op<Tnq-B^I-{wg5XPK92wUr
> zhEB)s4A0-eMCvFs(Nw{|Vz^WtFTyPv2M1Pf8P@4a_r@7KQo~YDS4bRz(m^PUFW8~A
> zbgGQor)h(vNA9q=TY#8fZ7dz}U8Zpo8&U;NwUw3=715mr8QFsfk!3il9)Hw<qmCVg
> zNxB+Hj6GZw?tz%6*QdrNbsJq_@drd1R7PAku8e~E4#OPh>~%PdfiM=9-~Jet3SF-0
> zj}KVEp<1-$DBI!Ci{hucRt)kUIK$Bf3bTazpd^~kX+Rek%<LXQeX@{|KYj7ebg5^k
> zFr}|a57$T7vzUFpp6KOI0$@HXwmxlHT%tctQ<TXkpxBs935u7Zd$RG>wrxY)x8x*x
> zKec$IY<}{drSeq`RCK12J)-~Z6&GEXDxQ|N6rJN0Q-TtS%l_D+8XwL^f9f?!Foho@
> zt8P3mM#8|L!x6lb!U#BQF{3i7S(bb<hUZJ1rPIl>X>`hakt_%%a<wNV;PKZ>Bx2Pl
> zCow(vArhtoe7;V+UT2HSws$t0%#61*aVI6^VTeW|`e3119*$V7(3q|DPE_SF>7N@H
> z0GCOT6!m<K??PNDhjo&Ptp{ZVZ`Oiil=@#rddAp*zd`a+&|3WYVR)Q4q7D*{)eYrn
> zuybQbrh>StfTF7K92DP$9p&;A3u6WV9yJqkaQs#;G?GY6imR)&u=M5Pa#nr_6EaVk
> z#HK_@s85Q<TebtBZuY%HI)5M;+SMjOSvuI%@#oGid3Qq&E0O&GTOY(K<B_5}oXXxl
> z_SVuH!4fJ_jOvjG=3Ey^&yPNAoyRArztfkO^>uAp#Ucr(ML2Iw2;KFVm`N@~P$O|w
> zy0;o4jH5McTf{2jLkwFl(Q6NGWUi&!y9ozs3d<=4Egw6GMq=hvyZQVACx9^KQY@Pf
> z!1wG}v2GdzU%^$((Bdz7g%rnmjgC>`Wg^&Y@wCP@j3_37=E)Y97RYtzS-=58ZvpV=
> zICPTbmbBi6Ai|4lyDH#o5XP#7MtK-n#&IN#u9g?co9kQ9C5iP6%w&k8Ftu3KH0-!e
> z!9|4U%Lq!^GLQp%F*I`ev-@E6^;VduO>YXNtEt@ap59{dKopm5lE}Gko?XJq<0-<{
> zIPiaKRO4UWjIH|vF$rK)c?~YgqI@(+bnA|tc=r?<75upETeThgvljT*dCQc6BNUG?
> znK9xMt2|%N*ZODPxGN3p(OBAUXQuSetr8cW!d^>|)+h7X)0bHL2OYAgdZXZ_>JWMM
> zWw&A<^7+WF@zRc6z`@yz)nb?Bv^`j?rP5ey3RQ7b+%+Vgvp3l(lcYH;S*xyK^U6CK
> z;nvf#I<NVYnuY;@32;c@yUONNiRNu+Kx$^COfCCdf%&qES58j+dE%$dGN*Kib~w^c
> zWw}&uF=NHB2NFb10DF0aUa6}KG$+9;RIOamt{$Lf+ov4vm@Nb=3?-m3a5}uOCc*{J
> zPgRk#6~g50mU?%J^0X$Oj?fIPIous+iq*4E_NMIhn>xvrSH@JleNetY7GJnteMiKK
> zZ3Fl`Q@TZ9%iVsGzGQ3z!0x`Xoimn%i~n+bvO%3aN>Vv7nhH5l!$vxXkuF97W`kB2
> z4Ii2vr+e)t{{=;DH>W@?_chLZ^AuN1SFn|^^>Y^{i<}=^yFQZs$Wv%2i7q2J#_N=E
> z?2e*8d=8fpR08u1LPp{1t*vcH`PI~+N5j4vE(0Ukx41x}&8-c$Oe~i1R?S-!Z#6E9
> z|He2`GUmnJZ0Wswe|HH!RC6W4&?4BYIaO1G>9K{x9>;1qn~M*q@mJ%p*)%d6LDG{P
> zo6-~oFx7+DSh)TbLH~n;HfV=t5#WP}NcEwT+vB!QzK(gX!CEKvLZvBTrry6Tyg*8k
> zisPS-b7~V38*kGRFJn^{q5>NT$%b#o(r&|Iu6^jS-nz|d2E17&r)F5p_bzpvd>epf
> zoGcA>*+K9Ng_V?O7bzaZ$ytbrldI$K2x-pmidl+pJXhe+HH#qLiT}-a{doV&+G3^c
> zBE^Sg9EY&C=^h;VpcVS(W{gdXl5jTco<QaKdcJ-|^zwMwkw?kxr5rg0iqT8}lR2&9
> zp&3A0%X22)Gw8Y1srf`h3U~iAQmRgele0~W0ge8A_c}YqNKvGE{9k$ua51xYiUP}Q
> zzf+?=&}{20k*P;TSi(FBqwV4tPa33clI9_Z8UvV!UlqWt9eFzv*1eq*V5Z`-mYFj`
> zZARoP&Y1Dsmb1ZjJXT}2&Lsf2l_x>3UO<ul6C*X5GVFRKlVr?=i6ZWrLLTL7$bz*Y
> z3SN|IIgXNkr`o-CAwlMb6%bltiz~8`#II?TSEC6VsV;o^dRzYTx{i=|Pf;YdZ@T);
> zKv$4zF}OguZtQf2^%8S2ZEkd_c{1{*`54xpoOJDxEn|427w^>KHX#$Nb4%QS*>iY2
> zu3-g=uv+HIlgzrjhnEAI0#?Fm5h-5r4(tJb%U$cv-KD@LyVn8f-a|t?r1pvrjgDoJ
> zKF*HYlifJ>@3xpPf~{40ayPBsRv9|%T@gi7JM5zhJ+7{!kbS)^05EYnQ2(i&)X1Fa
> ze&%36*VJtS<+x2>c{aq;%VY24UIIPhiI9+3hJlK}HBL9G#!c(p1GH>j_(F>xQx}}&
> zyL(kFbEMKzxIh@ltYxjm0=qkOp(I(Eqz!M0(ebGR<>qzf(1ly46;c|;5@P%}BhA*Q
> zfCILXZHjGJZF#3&u4IGU#J!3uxn5(%%-wyQlK|{zrvlNq=k9wi_)~&#hy@w9P&kh-
> z3%~FfVX?Le<lfPez!7LV@;k0l@Wdb>3>)i+bMXjWLju5OVU}1a40H*(hd;G84{*@+
> zdTua+D9KoUQw-m;<9=~F^`LHoK42;};+Qvziu!<TaplJX8%oouU`S7fe@@K&|E&t=
> zQinVN%k%Yo{qpGLieygF#TCF5->I@(@g-ze_#qdK)53S6nVu3ZStgm}oDQ2Ti*$IT
> zDRo3j?&K-)CTQAK?!SA6XD$0#E=_v>Rh6|Gr)BZSM&+4I3U03~YZpI?V>=q~?UCrw
> z9uJQ)9x_J6R87_mYm_N5?eqlW$1^V@FELHo$|j4L54#hqr{a6sy3@>U%3jR=qCZ2b
> zdaBHSFtkYHuBaHm*VkftN-9KJcK41o`3x#~bTXe;nUT1Z2OAf^={f4;s0_ZoEdTGn
> zzW&>{+lzW$Z@XQg0me=$stE&&oDn-;n0_{QqZ-(kA1?LID1bUd9o{4FX=E|#yb5T8
> z!xM+}DiE)|@cP#RfjRuC!<4Lkh$~V?p$R`|*Z_pZMMTP|m!OI7cds3ztdEHVg?ZN~
> ztrS71SZDZ~6{KW6jh)<YK*9?StRY1sFo2T2jN}=B;g8)=5D?XihQNG#U0>EVdurLv
> zu5FSy1MnbrW?ee|3=n=>o7R+sI7l28%%&h&8C0BM@I1hStM;9R=vU)Dm|z`n<-Xe=
> zj%^;{m1<`q9z_MQ1QJdgCojfK{A99vbpr--IEW6yG@$nSyW*B|rI~qM4l3C!G<4)*
> z=}E!PQU29nu`Mo{=zUrV%eACwn`$i(?$}t{0=k&r^u?%FS-TvblR;^#aHS<<3W=Gt
> z>$yPrE}Fi&7+tOV^kH0!HEyUW-B%ZbeQ}_RU3k^^NKg&+`~s85c?{i1wLOemx4DQk
> z0$3ucGvH{3^e7Dsnk7$Osz-^<#2ExavNQsqZcRV}=yK0Sf)8F3PrtE~rI03Ak#5^9
> z4<^sgTJQOKzMkmie;mV{d-)I9HjjogOcO_$PF$~(81edzat_LTxM4PL;aQ32V|Ts|
> zB1%nvX0*vgOrnedo&gVK?z9q{#<D)z&v=9f`vo;<)NrPAP`d)OpBqm}+fo7<(ew%d
> z1s<{J0tS&FO`oO~9o4Ams@q|zPRSOYAaRiSJUF`?(|JP2XQcbk`=M!V-cOh&4`gQi
> z)sMk8h1F?PIH2epM;nbs7{B&8YP!qRPn(d~Y&Ai%*JWS{OMPT>qeG!^l%d~V*1vvz
> z`OE8y2Yk47ryun!sh`2d=_oq&qXIQbFYnVuD|3gC=eZ`icp%<fH$amZ_=>C=afQ=B
> ziOCotxxT*+6QXotYuR!he}|o(;>O`>1wjtG&U=ULnis<1j*Yf-bP(W_h2r(LvPNw%
> z>h*9p2NFQly;Ft-?LD_`?HP98Hg>xKLl@p{px^X#zukAp9@eG#NA=Y|3-$5wwxNaS
> znFO-;);;%dFx-xUwfPXN*mZo2KbY0ko5nqbYTt&C76v-1XZsbcqZQ-~+!98*ak{sj
> z)$OjwbMXnr))TU;2BtUfsf%Tv*f+K|jcjqeEO@8K1f!7XIM2S!#=Dyeb#9iFGXDIb
> zwhHd7U|ZfOZ6})ha%{WUov6OyAzl|U0T0t;BT=Wz>_b!q7|sn_xavA;Hk6ODb(6*{
> zr8lgpdRK17LNs7zl0`PlxSQrv9T()WXM2f81uB55XWPwd;r*VJznEi$H+Qa_PIy~V
> zR7tR^0}`%1i)b!nU#vV@4STmlZc9Naq0YxW59N;(KO8*K;LKLxtB?C0j9i}3<@tKP
> zp6KPz4Q6KN6Mj6kiGq|Lf}zvTANnuHU;D*LeHyAvI`IeJ)_oii^bx9|X8tQx5s@~!
> zr>O)vKh4+dqkIV#xwO=bqVc|aq1h2-qeTY#>|yWI+$2g1DYLK?%k+$<HA^uoU7Y-u
> z1@TEK?gyy3h%-vtjxQ3HleC=E(1+=KGC(u8<1w56&?hJ{()3vIQYQ(<9h+$tPt|t7
> zIkB>-T7f}!W0CMJ6Y=yF4{SZxaMlWqxt%hmPrz50tzmN)3na06{bh8}EmY)13)pw9
> zKbrfVF&W|QiXWKigi$jxQqJZ<A^oxlzn1L8FiW8M;EPCAOGni%^;bleg-;t6qZJqT
> zrvEtAl%Tn3Es|cq#vjw+9atzs46r-uC$1kJ5tGcZg(id;M5bk2j*!@(%CFFc*ckbu
> zS*8E}mzSnrx9RvoCnpS;6ly2-+(Rku(uhJ|N`YPsf^*zEiaaebkF9!LjW`8kSqLXk
> zbiNLGzyfX+ct;1A`Fb0!V#)_PfR@}<q79{uM%`~m35&hMFGBeM4j6PksvvSHi#F_g
> z2JD(wL4fwK1;gBFDKoMz2_-?{iwVp$hf(qyl4>{xycGTrQmmzHWV$So7;AjF>S{3d
> zVuOpu_^A636z##g16mkEv!2_p1S*axu6npFk)}25@`byL+>#V0<XlWQI`b`*l1}U2
> zn^)bi0%^LCj9HN5wc}oMZ}H<EAM8X9mrEN%vClE^m{Au2!CJZwL4J?Q{;r56!b5lS
> zx$dx7*h};z?zu3QC{uAg$V-~St)7@!H7aqGvduB*$2nRzaZAZ~T|E1!xjTQ;uZQv{
> zIE}b=z;FxiI8zw*oVq+mF3;EV^+YefHlDf8F=XbAF`uR6C%wGP7Fbjo@IR0O%7gUz
> z2U{g)Wp>ca67%%SzJ))*gsuve-)gv#T{vv~$Fp`%&NN-pk;8nMIoq7ow=|MB`z0nT
> z=u+lK#Z#Yc*t3zl9!Y9iGHTiavC)-GtWel=ZqOr>Df4Ms!By5;MgP}pBK$oa6}Y2I
> z%!v2|48={E2DPWL3+Sz=HbhtY(|GEuGG;LA#oVhzE~xn7v~8MkoF-Iu%m-rma$8<*
> z%j@l^X~sc53bMO$KeX+-{`R)9o8@5?gF>*&8O}+OMfp`Eb4aM+1}iLj4#4&zNVwi{
> zR+*jBO-1N}yKBEWM>oZNJSK~QG)_u=nus?An=!wxi$)X<J-3!|6SxgP9-9gbABeB_
> zZ1G}{5+R;VTg5MyI608RQQfKh!%BZ7v7CZOD?aJ$9uIw*cGgQaCrH{mzb%F(GR<kg
> zSG()`Vv?INXAl)_@3bwNeXB+Mx*Jnyq^Bz^`R#rCUDJUKX6QU;S8eyMxCBV166ey+
> zd#3Ey_)(j2>8jzX4=6^a^*5qdGIdvx3dek-sGDLM!|BqSC32{e-iwYR?p6yvG3$=;
> zL7h#>6GEG%MLd-8m$1L%zFw@<#yQ=)r6K~Ih9SN<;%b3FD1<$<lx9s_44^N@Pi$^8
> z3i@_a*<nQS1O>S{mcWb=8#eqQbPi@$u<t3dbi!Wp_!$y`VxkyXqS3sA9YuJ%SeCAC
> z28fGcYk^5)93{W&rvNA=B~EUTF?d;=W`~g0z>}-xX|ndSlAF*}rWN)QWCF8sqwOAB
> zCi0YxJYUb(6TSTUFs3$P-1l7`_T^=E#gfmOH$Muaxd0fEll5~{)$(X)L$l#>$dPNU
> zIn}>%F6cQ1FzEITLPo}`<5#!hhwr|X&e+~VLIB?z>T_5MU8Wj2eqpQTyR-64_9>ss
> z5TWpNQ#1GhfF*UtNv`&Z@<kpRNz)Y6bJD@{C0kQmXB66!AQej1Jx(KW&IZi{s@)-1
> zbKg(oS$mFNj%(_<<AS4poP`{bHT9}E9_@d5S--t3uy68yzeOb;Ka{OoLPa-uI(<T}
> z3;}nkpw3sjWo7ay!e#2t&Kj^h1u=e!@1GjajvTK;7^;lOat153o<fkKbT$q8=o5cg
> z+kJ1I)B(o|iq<c=n=ls>0vRFhTr+%-_>s`X`^VNZ)&f+U$Nc?c|NHyBMo$b2Y3aTM
> zg-hOa{KEtmC4JR!2OAJ30UyJ2EM3tc|G4W+<~H_pfRLrzm=xoSk8MAGS1svk9*fS1
> z?r9Vj=aeXc%I>=Dios%DN0;VHW3yrep-7FWjIFnf`H$4-$&pUNmUl@x@3p<_=o<7i
> zrY{pJ{&HjAFe9^tD|8Um?mJZ$8SumsZ5P8>6nT_*Tc|9$j~o>nVy<Pg3&nl|K_aL=
> zT+W+gq*EKHIJRZe2Lr=Om8|1Ly$mf~N>x=RKBSs3W}eFgc&S)Lf8CRmF>={-gH2TC
> zh=odG56^4+nA@lgT8z|=ZMeCia{!NkA27mRmn8dz@F|~Sc4TZ?h~O+dJJ13sSjZMJ
> zcHcR2__}#?X2cMIJ!r&8nW93U5a#)MzMkmie;b}D;%}J>wbNLH|6slYody>-Cib$L
> zuS%GURG<{&u{CDlA`_=5&7;Cp;N(Lf$%gWvurOFNw@z}7$3<4*bpPGaOz2v*QJoRU
> z5r`Z;x$}gctK}|Lm#tb2=SF%SoH)sB3G`*1{wl*rw}TpEQt5q@1o#A9W{fBWz|;?@
> zAuy*(nq-ROjMI$(Z{~<BFxwpMn}TAlUJ5=+tC%(dE~_pdS(iDasu7#|2k2|jvs9g{
> zr;%zW{x7eqiof^!zUKj)=OJMjeY)n&N$gR;D<>&#8cfj~hL~T}2eUt%3Y^SyW|S4^
> zA`vFRbKpbtr>P{?mBem~!mz?<aG%D09~Jp=H2(VK_U(1N6D{X@*r6%ER^dqOJpOP~
> zmp$;Qz!PPOwsDJ+4&fCjxqkoHG`F$WiA@Efp2gW);U*d%DP}Td%v$+8wi#tGb^PS0
> zT#x^LeOd6~`!4reL)AOl7kz)f!+CiG5e|D?Xq`7X{tD3x4oo%O!uI%~h}@x=8*oe-
> zE2gcyzD;wYe9DR~@1Yk*ye6!(!U_zTo>0K-fE?lkFivKp+9JEcTP?G13-3!>C-)4+
> zB^a+E<PmKMvo)WmcH}CQWogi+OE(!0dJxFG|JXqD8`op&xWRqS;5GCMvNf3k>yolY
> zPtGVIbZH*>io1R>NMLq$%fd1D*wZ&%*T-ftP<j$w7@~(b%)~4wREKpgl!E+;!z-W5
> z2%TnRqDf!FZ0&VjJdP%WD`ss>8F@szb84~t!mdplYCTrPSWFUuD|)e>j%GQ<MFkBf
> zY%n5Kxp2lNXO!CE<7Z{}d_7-J^zv)H_$R2YQ^Wow%8)9`r%Q2uZi>@Gufvn};=)|2
> za>8(b3aZ5qEEFH;5c&Mh8h7Q6!=pj9YK^-nRSR?W##~YnS<-qE;ug(iWT^!1cD3`8
> zY0%OA6Zs0yh-Q_3gi%_V+nj_JUbz-=hz6~qkSNo;c#0gI2T)WPfK(pp=NSh-5I9i~
> z4CnJ+r(hXtpauobfV0?*)y25O*>iNBJG895TX21k;#~Rti&6Z;u0UP6QcRTkhm2n7
> z+HLi6MyEbw7uQk6u4GO3clnU}n7wi2BtATYbu3^bt|=-sPP7D!iimD11C~fbr_2V;
> zFX%4wIt}pfvE|duC8DKRLTVcupO9K%%7~0WkH>Fs`#3y*`+ooSvi?8+`g;8L_xEjg
> zBQTc~qf)eddJL)9)6!8~Ey@boz4!yA2ZD{;YA|18E}OD<EMQ)*gmD$QwJViuce<jQ
> z6G)ET-wRWVH1`u7Zc4S7SriaK^RT}){xY=v3~+^p#ZmM9{q6qtv11g2hB|PIWqZs^
> z%;1{2ihyUwc_PcMspH4f=zzTOk0RAbK6T8fn`E<;7?`lx9*l9yv1N^egjt>F!k}WO
> z%-*TW{)G^}X>8T5EVyO$saIr!^ogFQu)!{=raZmHnn7S-(E;|PxWEC;t&70C4iQf^
> zK`1!49@<DT@c<X=1jTUy!_?Tbw)j{W;Ss0X)$NXFOstR7HzKwm`2ai|h)btK;<nxQ
> zJ=eSAv^JNiz@Z`7!qIfXf&)QIv2`AI*&4GKM~}ERj(^$|x()Y*jB|}C){vkrEhBfE
> zw<H46ARo52z04xQl`S9I5eTLJo|kSm(W?9WbMW$fJzr1s^1pu?^VtvO=iYy*0=@Ic
> z^Z@<H1ps*lNu93zXSTZ()>COnyhCT-(F7gtHBGq87RVx8oG&#M`LTum<`VZuQE*?h
> zG`TfyWW{rVWXYJq=HE|6mTyh90{86kJQKt$PX=KNkK;$31jzgt**d*D$3%rrb{eA<
> zJ8avz30G)Ifv0{@EKs|QNeH){2POgG!FsN0Ypa#qt|DNAY94r>hD$O2!jrxY<EZ}K
> z5;l&?Inye%<G#M%`+t1bp01Kxb}3UqnK@(`n3Lx~F1XG&NhosYw14bU_DmoRIfNol
> zfE<oM1}-&<Rd{nxnwhRNxl?5vtgZMftbq&hOvg1!GWkA?v0lEsEXV(%Yg<2O+jUlR
> zZ0e%J#zvm%N${v0XT&%vqqC0Ry(yn(bt7a1S03MW6j-RqA`a--CzN0CCeE>y2s1yl
> zv|fDfak7?nQ*7$R>|1$C7-)1{hg-iN_3p>Y7&si5<>S8p_P%XSBATa662!>(vJrU5
> zp2pZ}Hf|KSsZyXh6Fv8(=cZ!f7+j;6187KSuR}g(QmI!vJku=Xoi-;#wb|qV9ssTy
> zx7iDp3rw00+#zpPg=1V6j?AvYA4JQwb=2iB0N54kH%+M@%A9T+91uNp?U-G>tj2;n
> zEk#Cz6L*g8#qXrp4Zqwxx>Ky~2L}}>=)MPP!uPU`hQgrCNpzS|;DW*bd_<XvH}^gA
> zY~8NS*noC?O3I{?`<O%9V*xdd!%M9xS@BqNY9`ds+>h~^V1@>UUi0H-aMA8BMqCnh
> zq4_L&-}`;D_+5-#%Ky?+`|2?Ed_7;!*Au<`VpA95X?XHKjEH9MWtoRL=U;e8W}|7I
> z@UzgR@X)Aa_wHJFG&k2DHbf;YVejccT1O^9a}Py<#UK_5kw_l&8VVh336G!SYc?o^
> z4bh&=awJ(qF#8gjN~qjO`7B)7UjyE-oCh+Krxs{kTp2rYB(KUPE?g-t33wLi;0bH1
> z)98btq~#a8ckL*WkXOJxJ}xIAoIYBqFlo&h7jEiWl?kJARXlOizPpmvj>kMVP9j>5
> z16G0A#1AwT6aIWkPT)ej4}_j>#go2>TMk?J)TfVg9ic0EzIggc?N3KtWeK59NK^Z@
> z#SE;}W%gZx+?U((*KaR41;?MizmKWJQ3zT8nDu`*Rv#*f>Um|8CXdOOjxRJVgsN_C
> zX@=sC!b?dt?Wo?qf9#<?q6}CR9hmS@LpvQS32Zb^FdElJIE8)F6m+9Uy5a=(F{E}P
> z#u@L+(8(Zt=GdyYk6pzHhQY`}Z0Oo?sQzG_a-+!!5Hkum3zwapRw1FHL=S+<xkqCI
> z_R4~_886J-mzF7_eRg_)of@{G6&jl_o;I7^?Mk!s7<|#kM)##3m&)qX61{P39OqtG
> z$0zJJjPR5_b^LwR)k|9qajbOSg?Ln*76N_HlGA`CBwLzubTgvVv_LIdzYh~<ACxUV
> z-vD~SC3HZeJG5;kChXm5V2u*1e7GWCv<DPPql9E(Lpa^guTEnEc8b{O682wc$1FW1
> zUU1dJd4|YdJT;Xy)Ogov`55wq@keJsYirp!Xwj)ArcCCXraFCA!*aN5bhGbM=mOyF
> zy9qyx!WsLshEYCW&)4(yL@%EsmJ@ur3cmj|6CQcA{SP>4avs?H<icEI2hTqTa?pBZ
> zZRXY-<shc>qdUgdG?j_ICZU`r2OH!h0egoLxhA?1OBTUiu5l|3axa1hwMGN`yi|?d
> zFI#c)>apqyhleMmnA&r%GBguy?r?LecNQa`D1hNC)7>-4D0cB_%~M6JKw)^lnhHY4
> zFKta-c(ZPzHcvg`I#siHw4-I4Nu4E3ol*dk$=sl4pkDD3hrF_<zr3#h_U+}iY?=_V
> zfB!IEydB|cx<zT=o0lagjWFQT>87*ZKNZ55oN94_PPaP~tg0za#$R-aq^$KZQRaA{
> z8{NuO0y*@HCjbI${M)zNU%uQ9<Z}EIjx)kN`@4*ILT7)i8tkXln^`tRYkc)`4VUPq
> zS8)#pp8Ikf??QOU?;j&?KIob@JV67yQ<%xd=)hg4eS*PN-%ObrRH7KkEt}eG>a8>|
> zs!DqJ<H4Wf{XW85aG3=|O#1nZUl*pT0kb)$vLwUsH@>}Dq$%Dbp{+Uv;HG<_`c`At
> z>Ryar0Zr5gME84-fRXfS6Jr2k4(VyCiTEe!%kW*xk=KxY_dRBJk%R*$u?oX%^x>kW
> zIs;sSxY%t_SugKc7P6xx?h(iKPqz9g2U1<*n%Wtwserla85s;$3sPBt5K#A%g|3da
> z)W9UlTQleD+1xL7_U_Ke-XxMpWx2U-9$`2O2wkB+@d(sF*S9sZFZFVx*IP4J07;?d
> z;uu?rd3OC^V!1$N<c9)l&aPj$4a8!L8*H6zkrWXB$O0<miCdnp=j(}HenHT3YGD4{
> zeB#gblAqpSc?8&G4m~Wjqlfa5%mbP60NA=Z`HpACU}uaR?oksX>Ol$9jOT=g)`w|;
> zk0~f<U|fI&on3F6dlH+ElG8^ZU&rH_EQ?^U`Hj!hiX1$$Yr+!1>hGx}8V^57tAnsl
> zXgrxy#W5T_>_)`^ASVyt4xPqBM$|4fP4GR6dN{M9qXK~Y(0E!q{k<uTCoF4Cd!VTr
> z^eDzud`H}&$ds}XpMqkgtK!AH0hTdLI6m{=|MGHd(#uEt{i7YH@?BZ^D7hll-c;1P
> zv=XE47Yv`$Gim-Sn~Su#XxHS_M%|e$!tC?K>X`Uyng!xK<0y8gxyAWB2Ne1CI$F0q
> zCU-<H!#3KuG(g&4UY39PvSJ#8!;5`cmobeQaehPUJ+{@@I;-3UGl<ac9Z}!ffd)i9
> z3N`J}@5m$t5IoM~I;3H=c@o7iN`_AYKn~!Ciy~afZIQ2`e5e(9E$dG+nYi|V#H1Wv
> zO!hWyd*j?4r+TPvc<Ii!0q%ORkXA=QpAv|9{!+~~;u1$lCq^H1LX^=cF_)|EWFZZ=
> zC{o9?5wk;{8d+m2)u=o?tZigeQ4sgSLJV7x;?^CQu%uKeXxR;A#VS#))#9>@|Av%h
> z_zm<;#UYIyfFV?#De)4U2Z;MA8(+(4fuZ3!ex>PxU}_u(1evy}>&$&CnI{WL(*Fh!
> z)m6QR8v)pWVjg821jT@AL7rTdyb6y8Y|?Qzy+ELkrImB6x3)AT5AvRo)3DZ!HP>C6
> zO>U>lvYLr4XucF%xe=-4ttW??$DO6Sv-fw^x|}#;paOQ8R4&ig^Ywf^(aWC^sK_V(
> zP{TcH&rG}%EQL<?3oUaG{mLHBY90n{Bw>u1uR|U6P)750R0aAN!_eT%t-Z5pZ4s|{
> zJnth4piMReG83IBTyNu1X`Q(fGtRrD5!Y~(SzUjx8g$C6zNir*Q0cTXV>#8=T;l7|
> zq>tGV08|_Fswu9KC?^tVEoWqn<=Y2Af;<|+5R22qIV!w$Nj-P7bn3QC+D0j%%c>1U
> zFH!{1Qp17*E@Cfiyg=zt&84?`d<zu1um(EHcN8~o_kDDB$%>4OxNhbY+y?8T*ZJj1
> zw8gW3bWsOokmXcu(=_I~nK@B*yTep1-Xm$q3!sY>QQJFc^l^!P9iYr+Wp|a9<7g}6
> zYw#i0X4T}HL^9f~)2tO|GwZzt4dB+cfm|4cAWkBxH&=06h=iq%YRIFOtzA<f?aU4j
> zVmCyJ*~_LpuB*7E;_9lxr;D2ZG>-zjaZ5S|Kr*lAJ@1R7X2v;1>$(@Vr4yI91^z5I
> zS7VwOU&XOH=ay75cpr_7O33=zt03+;yUTbwEKorqw-F2|h*AI>^v(@}pQ&YHDuN3$
> z=E+nIzC1X#B13q)XPk~yvwF(XoFoMI*v$_bo&V!1{MbzRt~|yw*KtOPaT3|%Ty>C0
> zgU9&&W5Y18OI&h%hfs$6RFR>Srjfec`$2IA-TK~LPuv~OWI^s5QJv7V&$1l%)NxC}
> z<o&oizP&7~PfRAiL7}U;+~(brx~I@FB7<cyf}%7F)-j&g0tTIfJ@QyEJqTkt`WP{q
> z`+d`!_oUIkP>7$e=j-`;qL)AYq=m9EA6B|j?03m6UtOn6H3sFEn9Rr@{nLZInMV$h
> zF^k|re8O*bD}c3%(q=Q*3u|l0#8@<|Vel5FM)<^KLa`^s+n3#Kvr-rGaZ^Sp1yqjb
> z>!!N)HV25HI1-YXWt6I1@@Fc7@UCG#GK(&>hG-pbxH7}wQoA!!XlN4pFU{!wr=H~(
> z<t*(keO_G_oD&j7Yw#X*Yf+c;Xkk%!Wqtt8Krz2|0&Zn7BwX`DB~xFl5LpI69|p3)
> zH4DawnRKzWV}oRc;m@wy0AdE0ES<=uVYo1ziUya=n#Q^~l3fjyOTr!Cv6UmGat+0Q
> z>Lqe|)2N!O!Uk76xE(@j9dKEHUWEiHH;SuebL(3*rX`3CFn5Ee(-@mTtSn>&mIujG
> zB(%tcF3|HfU$4!Y-ysLbP$GsZweSjokT~h+RPkoxpHg@om9g6{%PA5Rs3s)rVw-38
> zCWuBgwx>E_^jVS=!<qQ%neumWgrf_@n#D`;yOk|=szEX01+cNenaBy{DFw*C+7o;n
> z6RsnglursGOr_9>h*%h$>zGlnR4i@BKL~6m2fQ&v-GtIEOtwDt&TvIVJ0{*45kt5a
> zewS$rkH3vcxZl;)ULsv9TJ!NkayVzuEAi*eRamiHD9W`ihEgtv!TO@67dK?!uB}25
> za+|eQ7>w42P*&UV6_p(tM+t_@q8`v{U>*h}@DG^MqM|u+AeOg}!E}Y<WvmjrIVOij
> z|0&UbzMik=>lZ*T@<T|&4+b*9gub8^pUCi^cpAe$hp*0=nKOT^X2npUbfItA%17V{
> zt?oYK;RFhS1u*YJ27`lH3Q95Fwmv<NC#h;h?0XkW(6iwUIN_aAl0H`|<h%<F$lIl@
> zSs7W^kWK49^Jgf)sfEsoQO^Ujk#Ux$zIC9ZQOI{cEJ)R$jMP!fV~&G%@>YuRMaX>D
> zRp~@{#t+IkuU2802Sb7rg9jYBc!P|j2eXGSfn#khA&h}W!0!mEOgH6Bf4`GQF>nZ8
> z_tIKNF+s(!OUE)B(Ii=sisG~j9=A@aU&7Cti+!0V-tePi9x*tm7vGP<d*kHaiv;Ys
> zB%;Ql9>vdr5RMD->&rq8b*ND&fKgFxI#KdDPe6sSEG$P+t<Fc_yRD;Av{)g~-foK-
> zOx1!I<G$S$1rcVi2Xp9N-iG;G{|~n$Mw+1$^DX0LFTWM=BW{PKWpQ6826ZYp)s!*f
> zpb7aTU231I*!YmPV8Us6NO5JBxuT!{a+!t1tBxQ_(K-IJo0~b_gLqClA(o}wM3kl-
> z`B4>_p8&9&bZhe<t7un7dhEEo%fy4l_Rf%YOAvz9FuxsUXb3+v7laIR6rYXOHGw8m
> zX|r@c4#VOArWZ@MII7hY0UNNGs$@rgQPAx|?u9#OA7m;KsX>rAguad=boa*}Ue+b5
> zf6R{l^~>$+>w4Tx;7Q^uR@b8Jjtkpjj@9l?HuNevt<`-{%lpzKa_@Vy|JLS6Tu7@E
> z+Q`TC$7k)^F!lcJeMt4Nb{Sbtpm>oQNBM*<&)4(yeEq_z{RgQk5>H;&jGw(gwHP)=
> z{hx92EEg~%7gY1W(*8o7nwU{@{bT$eNk3qyUDVl@(0)_42`^Cab2ehhr~fEJcXeTI
> z#6eVmY8-lHvK}z)bHoZKw<}%9c5M{jO6M;CSfsSIjGmbi%EIkRinZ?G4lOPE{ZvE+
> z9L8gz!M4;9b65(HfB-~HYkV*xLG;JN^(e(h^AgbtQt~>+LpOCGt3JYy&AJU_Na2)<
> zkcc_NK1XLU?}_>{RTEmxzqMVn-aEqkNXbGPO}Hy-2tC&p(;Ik|23ZSj;N5MdOO_>h
> zZ`8Riehqk_4@=>zK*$tEtE-zj)V6VJ;Q&j)1DOL&nP%cmRPgXP0*v{~>x$U;<8Ocg
> z5qYjdqMD^R%#pS(K_qRMPnjes?6YLR@Z%R(-5sdHapkq4{@Q&~glWL;aTehI{eQpR
> zQBxvHrKDn7`3Q{@O~a)DGIO3rTtzHYRQvU4#0ff$0xsS6iQz*<Oak>$m?p>cEO=lM
> zvQ+)PPM@FOej0UZupr9m7=()OX_$8MY_MCq!I)Z3J3A}&r+mqr>X6^pd^W7B;}m>V
> z@XB0y()P5IGgE|xOkWfe{@#0Cl7MgbOvkc7U|h|+9)e+mUR@dK@%n5LC|E7YH2UIV
> z9smy>DLpXf=oJz9b!g@g{w;v+HrB=`=&EjcrkGp4YOL*nUcRVZF_ikTdiO3hsjK;H
> z$^q>_AnzU7ooR>IbJCboN;fy-V6y2o);#=lNCA(<>bDuXfR?5<<DeEly~Uod=j-|U
> zmC;LyMX!V(e)OXgO*arurn&QfdoPDi9q#$Bk8%_r3}m>9ryt-Sv5-kR4P;8o6xhY<
> zfsg_p&ovc-D}`({xO>QFWA4#Bz5vfH$lTezs$C_TnG0QHnh|l`i%g#cV+ti*5ym*i
> z;HvSNdf1T}-<{gd?vR7dx&~xVU0b#)HkeVc26H!F8^1(nP&?%X78?O$NaXFxJN|XV
> zHMEYJhIb2nXDK1&WCWFD3dwo0A#<f;J=$Tp+rab)w1YDD`+Zj$)jqymM@Dy@x_tlG
> zet+N9v}eygy5rBS!!V#nMHo~NKSaUKCy?gTUJSG!KHGouJSrJSc*)8YQRT2O9`(vm
> z;E!|D-?tt8@2nk*NIEOjkk@;P-`89Fu5lczX5BO=$Tj7IImyIFSO!T(zUQ7TZCv)_
> z3O5@7EnDLZeCW0zp#8qtBxUOcQGlw(5AS<uOEAL;PlC#%GOQ>iz{ty5@E#kb?&~C+
> zz+u@hvioo|pGKOJaUzhDQE^_b^AOBOiYPzu#$yG}96r;pQ!=6lqq8eesZ*D*L-fhk
> z1ifOS;;3&TiN!|7T*XG3G&!)7R9|L-Oo-H*gl2zd@`PDcf(>nnniw-Yd@FCQIv;lP
> zc4s&l`s{Z?<UX-+QGRJpVAaxyNyOWmyKzjS%+g~C;+CaLVcfg8e;wKow)p!N9Nz%*
> z!{KbvSc)<CamyU&<=e}m?qST%$c6E`Ik4-P1q(UrJb8d0^D5{uFpO;&Yoc0ILm|eV
> zy<6K5HLK_Nhxhyb`}_7E-|q)*8PMep`lV6D`eoqqgf7q5^YwiFdgvvIDl(y!84Ofy
> zDCfI#9%D{0QY7IlkLMWwm)6P$!j%g)BYLop58rcsA5$d;o8*U`DZ;a*l{j}^A2Wk>
> zv!SZcXP&XhqNJGA7d_(kOw4Vh|8=MoTJ#kqW(l)pnG0!h$KXHa*2$#F=4t60w53Wr
> zX)dxydpE{RtGiU;L0DP%CYg<76{b^YVAkK!^kol`ELqy1KZM8x4!qq{;E-&9w(e0M
> zn9HYj5<iL)ROnDg=dz!+!59}P&R$Kdo^5H(K-}SP)*MM9!XmhT@huR_H$QPunX@CN
> zI)1@avYS*m$w*w~xmn<*cU+M5n>(w9uQUV+$K~|(bwvTRj!{*Ic%w$0fL|1}8RQ0n
> z({g;;i`P;xb`vegK9Id9g-GM7Xs<Po!#Iq0cQ4-rOfuV}kyP01G8o%=92g8++QR3?
> zxo+n+dgBaugYOM!5n~omW%{G}Zd9;o>g6thQ?5%z?8(uZ7DL<xC!emIO!M?1X%0S6
> zuH-bM+@f(WxMNjbZ}Caa_N<)JWb)P@x)}q8y@Qd3Vb@9PQf<BxHOY03G%cC&MfQdk
> zGaNn*oruypaqD4F0cbr5_ak#gyEn#$0xo5V&>N{<Z7^5tB>?Lr%dmCH<9De_0jWp=
> zq4VjU@T;2}lcHk-?qlM@FX*gD&+(Mr*P<)NZ3&BKg9*pIc5_>BGTyA&G{4@K*VP&#
> zTZG6EIStk#BXJou-RoF{u<m;hWyVGwZ|fLpDP5DyG7gK01y5m2wCO<Ux3>XZ4gdpF
> z@8K{eW%l@lF3;EV^?d#6=;ad=B;t$gqw=JxXq!Cu-5+IzufzP=0{N3dl%IUbqdhu-
> z8U6&o&;`a!|0;DhA=9Lyw)u;NvM3ROBL{t0kkQUbjDeFf3bMUhd`A>F5mLb>$>rb|
> zS<PgTb0%NmGC2ufvLKH|Cz5;EaSG(>(I<|xD_$6L>2g}9pD=Z?^cA>sf+{101{40L
> z9=;(V%8y75Dj_Oy0STo}U_66ICD)f_IS%E0>yVT{t4ee9`|$)HLyz6Y7o!O7o^S#s
> zF;kstSc`N?G8H<wp<o#&MJ>z5xa@=WHFf-&pV-mOjq+NZyVPu8rSBg*J`;(VyVw1u
> zLW#Dum9v=>VrB_*{Ek^6B_~jvzLJezig*(OR6xW8Fqp*!)=<>rAHTjVz%A$;-&SL`
> zY(t<mwjAl7x8bPP1Eb=gHM7tak9!BN4_q)GooG?DnID;fPnZR7yTLrOCk_D6)9g!!
> zV1m*%oWrXr?d~kBxItaY@78TT_lV-Pf`@R#lC%y_?p9@CRdC+g6a|AT84ZY#QRNti
> z<1VH~6ThoMWt#gA)#17#&ni!kE<SEdXRFR|PR{<z#n3FUkT~Oru5+Q2yR@qKhW$E;
> zvp{`=XJ2Oad5jrMlUqLrhQUY>XI4pVfMR+#l_eZb7(It-4+Ff;v+*p)c~a}C1%*1=
> zk1Q09WfoVOHirhE3e)eMk`2p^+^OQYyNzQBmgey}Xna)q-`a+&IKrcjwL(XW;x`Lb
> z?-VZCN&#kZLj`AyiopP>gQesNHM7L{b;T!RGd`5v`nR|3xA!}&7lE1Ze<!xs6S_QK
> z&)4(yr$#UQ`66}7Hko~mc*-~A^h^o|*z);q#_K^OS@3fK5H8Dz-+72YetviO=inKi
> z8F1&1`iw>P#~V>9OJm`j1P5X{68jz;{f_v>-t9T<8Dt^P9Z$}?GX1-ES;t>AJ?40f
> zs)BhUy0xh@YO?!yt{)(0uYk*IqmvxQ_-ShXip+IaaTq82MZ@N`kM0Aw+3|^rMm%O9
> zR!jB73EI`?nrh?Kq@`-;Q+a4uBToZq*$_W?qDsGwse!{4g%HOtsKMJ=@Y3gMEM&Xq
> zYrV`m-aht`=_1SPDBLiYXiyL-F0h)MHGUqY%s6FB^E#U%Fp*s56j;T%TFx0eUD#U8
> zd7cTMxJmF}U0Y16nj%T#%8%oq-B{ojtKI!tJ~nfp7fqi)Ox{h;>6jaA{Z&2G7HXJV
> zy{rVfJjz+TU+MKsG2`-s&jbfHYiW}S>&=9hLRs#1Qluf}r#nAV%=a!eRx+)n4X)&z
> zic&pavR@s*^gg|<(^<KG8pxz9gr;$56^CFK^q@&0q-8Kjo17ue^VL%-B^8EM;N&WO
> zIT79hIkWZMbIx{pRSZ+oS+mU{`NzaC-aD|YmED2mupnnyRYeniaWXq}=k636w=~Z3
> zfg}Q;#;T>b%dou|H8BWUdUwzilq`w&APA{b7pAiZ3E2@~pld1Jia=kOFCEqYBCPF+
> z!Of&J5wVmWOkH4y2&Ea?1Qzw^d@yZJS!Y6nO{Z0*6`SnU*JvLV=E-2rbQ;`!&E9N>
> zbctNA@~Al$%eQ-f``CUT_F`KGxsV-UagXvRXnDS#ujlL6Kriy+;{M{j<04~Mpl3{;
> zR2swl9a3vA_g5A=g<kUIzsX5^u&wfFRwI81TKEzN_?eyBY5MfZpFjPb!W@X_=$W^s
> zN3HAlWf=D~n`{7YK<eGQv8P5!z1kzH`YCA^B$|kpM+S$Sur{7DG(Q=2^`xfA;xulG
> z3>gWHcoMH+g-lLTa>fONWuz+YMO*1TIP_I~9JwVe<E7czN29cj%#a}Nj|RLN9BC}{
> z-pwhMk^A|vDScwmBfhlVgQE9cnC2FHz$%Zwz~=Q1b5siu&$)yo?i%bb3^6*Ga>u?e
> z)>|DvrCUF0m;SPj`Nr`H-(J>lugiUt`>k8iCPUPL8t-@y4r~eYDXwe9*_kZ}JPl8~
> zaz&!JJT`0{t_jS3M!vlsU%f6aE_zwVLD88{ca~9>(dZn*!WEv>X7sFMrFG%jgI7?r
> zK(o{J!W+|=0cskqLoKa9s>w@TYirrC1>I?lV+=(mG-zP%WmWCN1PL@7`G)=K5B}&*
> zhQ)6*v$>_2RZCqDRX8*upXo-)F~|wkBnQt^iQvOwSGWKVdukA$7A;F&`jqzO)1C@Z
> zsAQ^y6eqT@;+fdmtGp-O*yp9V7yx9OMZ~jfi<2*w2t<W$P5LLcEGPd!*VPyZ;g)tC
> zR7}a$hKnkfjGP2GHe)ft80CmLT{j9pmcwnVOHHy;uw8<c_MO@~QCR&ThjRmf3P+EF
> zTotnpE94<)S$$%u!Wr7AH;NcvmNP>^;JSvJ2oaf_c|P1{Px{l99tX<Irrl(0^ab2w
> z0QcIvLYMC!`#UsaCexShPN7fe@_apC&)2VnUOpSV@WUcK9kaX@R|gT2<<RsGlDY3p
> znLTp;+zS-(KH7P6W0gJ6O!y+k|4fz7e>8P^_^<p(6Z1KAiOELADl`YNg!-k4xr7OZ
> z4<692&o&7MPqv<=sW{MvMR(N=W|T#68-4Lmb%f%D+`AcV%jp?k>I_SWchPy{teHao
> z4w74B8hFl$Hueq7EMfhG$K+C4&Nr~9iW}^phO2X^K5<7O8+wMQ9a{r(GYcZrKqw<n
> zH;j#e5?99sI<7%_w18P2-xwvY*)DU|ZKz+l<yga6Ua%J%G^zuf9Jt{4iua_AF&ORY
> zAZ(rK@GL&g>ao)nVlDFCP*=3BPO_a+92JDRDrV^EjY`!lt@jjfXkw(GTHRFW0?9s3
> z_s3AY&{1F=7sGus+P$lv&5IfD|N63E-g1C0ly1#??LJX5So^BSycWK?r+wcIETO9F
> zK7(U*Dq9yL4%NU=ato|lq~Ux;gFlHaa?T;Su1++WWqfk8J{G~BM-u@9_;m1nzuZO5
> zZVC$~8Z<kVVvqlIy*t`vs?+LyS0Tz})_ux^nNUGg*i>@mV+a%O7YkQ#LQ#cFnp`Kz
> zE&3FJ`_e);PMZE@pKm2D1h#NX@0Cl|ry11XoB4RzIwk>TIC+@rC7+@rLYkA<hx&5O
> zb@9LOgr#w|l@Jgm;eqJWzes0_BRo8>Ri<TASq*v`re2HrhU<uO+&-^rCWbbRdxlx`
> zrw4Q8N!0f?zva=!GWpg3Ga7AMyy?;q!#%sXyLkqwe>UcQF-QzG3-ox$O$VRx`v`Th
> z*-P*8<9p=!dcK~o=j+diUgW}$dQgael0u*Jmg<viz`{A^k1}2+TwtRc33A8j+xRj}
> zNzY$Cduly^7X0}zh5m7c%|pP$59b*f{}P5?c>FXvI~EZe{d!l6B{lK~JIfxQ@ifKr
> zZ}6rTE$kS^qez`RYSZ!fgcM{1RNvEltcCze9CIh}v4>rj5m_k6ZDtZpO@IVs!$nIq
> zI;laAQDN%=V~%HM+o%T^3ytsMq%CV#w{}#+q#BEEST0K|6Cre0_3YW6kATRoTX~=h
> z1q=p+;0L-D)xL#e<V+(2A0xf-K28AX;Gm>rkdg9Lwjs!_{@8GKq(C@p;ggyNH1D#G
> z^SBMK(nSd|{kFUvyD^f#O}2Y->jMr67uSr7%_$8sOe}|voQgA;dp@&)2ikBeQr14Q
> z`Mw?($({yiA1X8%#o3^oCF|^fAIBAi`UYkOdr_FM()VGsC-Wr@@=WjM+ZJ`LZtbGB
> z3Su_LPFn#N5nmB9r=4;h0us?_>XLV_Ov@S9CJ3JyfOV2amsG^-pBwWZ;vZD`pbUYn
> zw+xrIWh4Mn*W4Q}Y(0V;CA2gKn2Vb^6_5Ek<f$2mb?j65W;c%9#>qOldzS8Lo>QHg
> z1J%SBr#J`LD5lE<U}6cBDTpW)K9OK^O0&sdXNu;FM^{OP&w5HsF!yjHgD{0dXTh&?
> zL(4*S#je1U%Z$lLT6nqJ02zIvxC{)6sH_XJ7OY?3fWg4yRr@ZhgA=A0QI0i2JyD9&
> zWAMSo1v9SsyH6wWubYL{bmv;<<=RXnquM#2C_1Vv%YwUd1D_02#J&Iiv1uOVzUfaq
> zUFSJ+dA^>n=j#_iFIU;dXM>N2Xy^2I9WL;REoOxJ;s=wzE|>9(oZygcN=Qa4i~R()
> zELrjAhf4Hl2Oo}E=o6dd>tN?H=c#EgoT>Btpy(;d$GaQjjy+~&FR4=vx0={!5Avg|
> z)F*cfqR8>+{i4)`<1b&def~GP+xWuccF?ZtRDDZ91(DjnzBsPp#7O)TpiBLURZH$Y
> z5SitRmUO&RG^d>*hMzQqxDCqq%d&!KB=o*@DTEd;%KN2q^+^%r2i<I-w6iz_^r9Ry
> z6v;Jd-YdCM<s_{fwxO!AVF_|h2z3yrGlcJI4YagD1A`<91q~P=Rq}DXUUi&-dCSKA
> zeIxJ4CIde3e~k*M+f1(DXzrlZTF~G}N83qa4L-}q=X_VXh~cPi{QEDr_M$lOI41AP
> zRDlC>ko6aLO*sDhWnElaLL(Y-7dRrgnkCTMByb-FbBj5Z;fKeGSQkZx+i1TZhin%s
> zPy3!t{od`S?qOET$s#Mcim6e_(#=a%_LOnza=G34;s<^nwp_Wd340X7vrOSIxIHnj
> zx>*Ea(*$~1`f-UHF2;n$I7rQWglke{YbUXvULkEBG38Q8;RhY-L#0j)h0>f&xtPU5
> zGto#C=nXe!lDmRV#+0a7KiWPg?}Z%Z_+GFHirk%Se52j?ZL%Vu*;*|;%9={z@rIzN
> zHJe>vlwn*{{awqYKc!Z=7kOR`siF7mUCvzBRz_zn+7O!$8*y6=tg;w1#oiqVU(dU-
> zD}zf`L2q~;1Hky9vmsUYtS9nC!-tL3g4SlCKrGq6Fu>CqPov1Zp2x=T`*3*w`}h0b
> z-tNabphC4Vc<G@WdqS7z>-l=Vexcb5|AYT5pTL3e3TEOH$sw{Il4?*|q$$hi$)Ky$
> z4Knvui#CSSd|607-Tq52^MNp*F7SiredAADmM>tBO#~D)1T8TiekV_opPbQH(45AQ
> z6J`ku99I!NwyJmS@e4O~vH~$FN~oL4qL0VYmth+<_&>)#z1?^C`Lc7<5p`V~k+ma;
> z&SEqIwHCK-D{OXZXZmCj=3$zMudy>`emjdr$z$*mqa-x-U$g{nFgs@Otdcc^A_)wf
> z%xd(aXIc5el^++!yKCpMJtG^WN2MrT&KNcc7{Wm-1M>}rW^rLJuHNauNIT!HyG&Zx
> z078so6@xE#%>s>T@0;xl09APKc|YB>(XcrRo9u-nhmIoUliVJPW;r;ROTC-GX5>y9
> zA7&I@V?J<e%Bj;5O%WP~QKMYj_Sbd6(B}BX*DuRUYj@p+uP+08ftrsyLuEGRQf+Qs
> zdd>7A`gR5#o5?arGNKWFV~REq<NLiQR4#}j6iN~8;)Pm-nObHa=gMQpyc!;~7GaL^
> zkTMnnAD6u62891_6}?oJR}2+lyZ3rqEDc@Xd>lqF2J2wW^GU6&t%d<7GwX+>o;s%U
> z_IYk+->GB=Q8*)<QaJ5uDYk*V*Z|@K6<W(U!IG8$eqM4c87wu+bzLlXG7RX<86$=D
> zxap=@#JJ7rfkY?IscYm^g{2JJu@_A#WYfWcW~^mIY(8aXQ*1M!52KFbu6Y@J$Yz@O
> zX00DkKwrkcE?A(@r&u*{QZyb4gAp@cFE^vjod}n`f2l`IcGuo?_gi;m7q5=UmS%(B
> zstCdrE*>is<^)KUJ%Gxw2EKjle}5a$<+x|D2JUWz@Wd_8*Yov!{bK0l0Z%NdaCuA^
> z`;jkMB%l?M|HaIb<g!vm_=itfrVsq_u;f(sPZJNhj6vverDAx)gHvLRV?zmcmc=|p
> zsWRERCy84^UJ{g~&-dag%jr(#>Z-#Yat6_-m%<MO2)e!Ucxo<GGWCX%Rp%JDqe^c7
> z{ulY}Z9@P&k~GX}wj&uJ`3Bgd04EVIU~q}EM2m2YYPJijfH6YRsu8_C0~nI2e`wgR
> z%_`~WkD^ext1YQ$bOGulppJc)ASP9>YVEhGxMcxVu}z)YEyEeq7?hHCG(~uiGZn4Y
> z$Xv(qSB6-JrYNW{;Yy6#WmHbX6#zjlL;7+Q9a^dL-X}kw;MC!_HWU*@`BMj$JV%>T
> zOclxnq}Vn8>>_*Z;4TD4%B~>c%Mk33RLz&Ai3d}xmQOK4RJzMc;P8Zk^<z7BN7OEM
> zfgAOr$$n#2bAY<V#LB1)7Xd=hBg_!vjAQ=38U62MN8U8>8^;$6Hh|t*v$DG<*||G$
> zSf!3cCi<ckbCPpTDR#rHO>@OQlgCc!@~29=dgWCr)Nl+}(%rHcjK`amtJBq}z>aXq
> z5DY7GlYzzdbIG~Q8OznhOR|F?3Q|(=T^6VWLYQRw?$jfeH?=d<Zi~&_L{hR+w|`v?
> zZHLc6(7Ix^2{;;<$1S$?8}}r_MMGrVu$HVc86+IQW*Nhl9yg%c8;%bYJ_X}Uz_J@s
> zvT;X|R0djRcmN<2lD(lbbSdiOp_-OKbp3K$tkr_fg2lYBbLGN2kR3l;+zLsonVz1R
> zBjo`D(Vfw8s9h)O?Ka7-U=+>8mz+G~2p9W4)cLAxQJ&bb^8fz6c>}Av1d-%2sCmAg
> zujlLe`ZZ@SpD0^?__H&BnVt6?&{V(IPjOMCTGDK(GEuS~Nc&ItL>>pY1R=pn8F@tF
> zDuFFfs+=NRxG>dzfQy*9J{@N^U7|RRK9f^2PFPTP%N;{$+qJPco|urkS|%eZ0NCm1
> zW1f97(ACmvRr^l#_?L~}?z=nulrh$1DM06AV)n|}*FVKv;03x-7=7+uHB`Ayn4~QQ
> zx8PAN&SJ-D!W)jK@4I%ap)jemHrMBPo0&94e&iVTQ)@X&G<-fN;HUFdorPjks|}Hg
> zF-B#B2~0|jp^82b0u5*Dm8{DigP>Iv>dL1Y3?2l>t1%k6!i8Y*46<At_)v03SbId0
> zSNmxT{`0za@j(sVpulewK%)$8BaGwg%lgtYwGfIFIG#D%&5tVDz(;kc)Uppnm8;Tb
> zjzgh1i1!5{EwCui0#udF7^W@M%(qzo+FB54#78V+-;cwEb83-!=AY|H7tNSLoc0}3
> z9e$Z5AYbMdMp$PHO;=vuHB*I(?gARE7^+nJX~QQYhs20{SHpk^*txlF1Fmpnncw#Z
> zMqH|%vJ;oO7caXlO_iqP87iz!y^)KGh9t98%x5Aoy5}$^$##dk!yZV;LY@FSL$;0-
> z_MSK}^J<ZEg3^37iCPOc5w!VpH7NwSfI8(=7J6jCQRAa1H`oxAoab_N4$M=Sm60<I
> z0`WlJ$ZG<<tz10j3b3n<;I7d|_NYGYibjw#jXC6P$@|eRPSchwjV4!mGM^GxG*Po*
> z4$_mlqnD9Qxp^N4&;^s{;ppfC*a}&X@7X;e3X7*^CE2{?04>MCe;c;QyHdrhbrrcT
> z@}QCUd_7;!*Yov@pcnZgNF#rw9C-j>=0QXn)AQNIRA#Nbe^CKAa&kSJGcP{#8Q{x~
> zWIvk{v^=8Cm0W`y3H<?W?6YB3h$vj#*@GnDtzD7x&<oQa=!lxer0wo1!?3_5Yt#)^
> zy&BrC&NSME_asbrjV+h2jNr@mvWV)Z84-afCA&u|C$6Kc0t0$UkqCG!1Cdj(R<?Lb
> zZ08z9YO^A5@i_x(+)YdBDqsjYP#r<s)TIi>H~}nUQ09}pq=SoA9=c!AY}Q(VGDlqI
> z5OJABFG+!eY41!}f|}weI57BHOAw45_FeX2*({LYA2{)KHPbCM_!^F9A@y2aF=Ak&
> zog;CgXg1NU)+<&sm9j6WdeLhS_DitfkVbc027^X&-(iR(ZjOvPd-106Vt&wqPJ&*9
> zcJ3_KT+|l%zOOp<!?_-Yux{!d$9B-?l(&Y=lep4>i$;fd+uxLhkDFz70EdB|?I5oI
> z$ajx!zEgngSL{7b1S$luqCltuEjMB=>7NAwG1nq>%8tAM_?XK@un+nY`w$(Cws+iO
> zlRZF&apuRy*$<>@6*gVGF-)P(@llhEK_-eCnR;rf^820xrS3Cl&Dk8AbRT)FM!A%d
> zqe7v^8K2pyRqosY@{a|9K3oR2IZQWmGd*tTN9;E75JzH8GL-J<D-tsUuh@#TcS4R0
> zfI)CCTeEJA8N}-uF;FMbo1hr^#-jmT(-FfuXsg<=Q1~%i0(CiBbQy=P3FcrH%vvDq
> zUR=3jpof0VrXK5y&f{T~vG;r;?2i9q?b^g*nwHrwBFq5DRc*ME_qzm7?0_r4Fvow9
> z3AX6~HWjE(;PQMuU(eUCi(Y;P(#Svl>pYe6p*Q5PNBzvHn9sp36%So7(usre2@;ce
> z;1hx3kH7bVPpSjwL)ap7|Mhw_Ruvea+&6Ob$y7~Bg+*!k8e^Uks+LxvOCL|}mqoRp
> z4CmnV{86siFgO}>05%j9#g@rlc>oDKr0J2JKt-3WP16a?YxI;dG`LYO23w|U$olaW
> z(2JXDMW3U=<F7s4EW8w-e5e|ucDPNBEK{0L4MGUR0M{;i|C^?C)vSjkn!;4~Zq!4e
> zmpa+P=}~z_5DFXBP3xW^3b^k;s%r0Z-`|%|&#MH+&5>Z241fW_&)eNh)T(M6R4a6j
> za~?=0u7LFuB29Vt2bk{YG*}1}H>COZ(eR}qTv;`s1_J$oMi4ynK6VDhjd`%HPVTqR
> z2}DmW=77weF}ho4IXe=^yH>NPW1t}XeDmqb``sGDyX`pG|9&kMWQc%EMW=LkQ#QXu
> zr5Y$(#7AjVKa4kt@uuqzX8S`)=&~*)=f|tz+WW6eC;S0>9l1$>XF+(Y3YH3EBEWtx
> zH)&<Kh4&x=<|{1uEL`Pu8AQFSn5rx(ncm~M>|Om5Sc24K$K1Wka5Rja#q4QCLrt|i
> zQA*``W5;bOYgshG%p6&|priq}bTfJ;DOz^+K~Drt+7x9Rf-#d}&Nx&<dV|8*V-#s1
> z)*ByiQ5zS3BRAYS5AemkI(9|g0QMHb>rDY&IY+CY2WB2xJrlIVn#7LHc9S#_v|-iq
> z+x|-wXUA6f^b+7g;<cfA=?C?ZBBi(0vD!nF|E}m|SL6xaYtQ@SKl50BzMik=>-qY#
> zqnCdc{yDiA+Z-ke)KA=vL&85R_|HR@j4ru`Q%1;x>luh9?^OE41-jLr@L9tjLy21D
> zm(JmYdTNgptvxnR*(kgUf!!+_DX;;Ly-ub%IfcI0NyV3&Y8XP@UK)4<v21jw?%rKC
> zRX{<H=!s2xm|?vo#f&Mc2UKINi0q>a&X!|<{<`hQ$7UN~q%VJNqD04M!rN44?`CX!
> zD|R~Rs+92*Q)+m%79dyi<E+HQuZ0sdc87BAl>?<x_ebH#=CVrKjka?3RYU0WB>IIh
> zSYZQkDZG(U=-h|af8=SpQMDH<>H<Vs5}7I4QEHTu)UA(ggk@wuctjt2F}U|lbGXe&
> zZgDdu`=1&|#aPDZJ<akl-`W_P+}1U+SzgygOpQHgPB_=7Aa^ldAGSZFBC74S&>@;V
> zXf51>Z7?#xZ8u{Ey+j$>4;=*c5VDseNfC$<|AH3#<~*bjNO&4a+QDHPdO^Gu5LU_`
> z4y+61x#AWoA}A9P$r)xB%99RA^}YfeRk7BPdLPi`xA)C`X|rIxhDBBk<2`j7=76gv
> zW$d$XiHw>?N$1b3nVW@t$ramRd&~sbqgN`d3edjzB^OX_)7`|sb{#PK?E}zD7*t|X
> zaV#~99!-QK!e?JuPl+L_XI(%^8|mm7!3Tyq=;VS>k3)BT2u#$exQ&JA-^}02JSy<N
> zaSjIvZ#T2R_KaYCJPkh##4IWJMsFenHh#1b#u^w#l5y%zkFk=6b8(PABU<-3Zs9)x
> z2I4kYwF93VH=rYy{^2~^>MADlyyb~op0DTY`Ff(4e`p9p)gwoK=vK^@?;?`~{?qR`
> z&ut#Wy?EWtpUh{PB`oGsGYW)Ot&L*@k!dqd13$GrO9c2n9KagX4ro8_2GN50QNu<u
> zO09AF;n<_GM|?p7!F4oK$K!KV1+dy`1(FeK{kk2{QUmOaX_EqdN;(ZiMq!P`hzcMg
> zQ_Pl!rOr|+AFNaxRc-7YQ+LQU9ZMk3GFzJzFH*unCBZ{{EERGE4(0BoxNPFawP~eH
> zX4k}Q3g0{q_(ERJjx3r*mD$7=qX}DJAh%Jos-@O40%zL$ec$(f({4Pfe|Y|&A=<4l
> z5(PN}3`CEA5_XdXm6Aq_Mpj_vtPAozjiPfBcE9N4LdjxQTOZr-{bM`6@vmQR_}AnA
> z9hKaHTTCuYHc8o49`NOc5tAI7N*>5G>QNmNEF*COI(vd4_JB#cN1VYvQ$Q4``6#fY
> zfPv<BO&WZ;f}Bgi8gJ+m_K$3-WFpl9{dCt~5@XT=D(;K0$cu~l<oy*s3PBrV5D5E@
> z0v#zsQDI+aB-LFywCU0QSHCasxO0l^?dw{ImqN2~-qV~<dfMs9!mB1Pk<+)*Gk^y#
> z6fsTs@T-M1W(mMNkv<etBivI!p899Opdh6DyIb<P--%3PbH^>%<t3$4=9(2Vt2!VJ
> z2yOZhT?la31W?Sl)ka|wO(i)B7y18T@7mhqHj-;q14Byo<{|(8Pv#-9Mb4lr=sI<4
> z0HhRK&N`c!)u)xox#8BRQ*|!mVjl(!ZF4OO&T7!`jJ0S6^hNe5fq$gp#*U7ZntO~*
> z*ldInBiUZMV{2iI#rpQJ8Os1FJNSR!vC3eGZNDo?EX>Mm9S(Zs^YQn7Tn1}DAJ4}V
> zz5J7hFjQ$$mGyI-j(G`ZE_5f^jGWtz(SU8GDHr#`>p+*nS>kX_bIk`|3E34_`0LD<
> zth}eS_%lBwNIojkm7AuFb+hlRB9lqzQ-=eT{!1Luhhcc6M5YGQSPjz{)nVU~tVPbJ
> ziY7GJEX*KUgwbjmMAM0U67-KiFMwEk!Gpdyn&V*sT>I1LzI#i!XVDT=z`%jUK|yky
> zb?|h{3apeK7pD^{6=uHFE=5IHBPRVPLyXe>!0yGwtA@~n+p`x99%4NTl8AB8%1kYZ
> zmrn0`$lgrMjam)X)j%5KeCXq>KrY_qX4X|@5hOl%D=m>n*)2CiTqg8ldYkU0(zpcR
> z?$GBHk#G0T{P_B^etl^gPdUW;DpPKt6ykJQHBh{gxG-V6Z_ozt!=e!FY;mJJA7ojM
> z__!2fT8Pch6QDTo7F0H9MUgbR|2}jV2SvN{f=Hr5=iq};^{P6H>|@dB1+E7oLa)7&
> z#PX~x0+j)B)L%jM+}fU3D>i_Zs3Yx_v#-}-9Hf}ptK@ZnOh6;{hJx903`K<bUIdME
> zKe#t{+pBvr$8)gL$mJ!i0^_u|tEm_aDmT<FxZxT+=i!t|5hOHb9HMo(0^rVD+iV`V
> z;}+K!;T+I|PIWF2m>kflIRh;=HnK{qc_3a;Rr?_l3%J#b*IZrGQvXvt39#yR%sD%E
> zGX@;jDHiO_PngXn*ix5n44S$@otPU-7z0$n{8l(`U8ZS&yc<%RV3faUH)_W!zr78_
> zavx`!dO|#G(gFr*kG(1vEQ9Cc?*>|gt`8H>cBFsuQ2zOMcs`zw|1ap}06t7*J;@dd
> zhB@Jt+OPcN!aKN-0Z6pUPb;v5=}PfGX+FrTlRZ=Hh+e#hCmdRK`{AX_GkeQ0nC0ZL
> zo?z6-p=CII5tqn&l@k_T(}c+q+{mg=*lK~2Zmm(N+zBf6=m0k1S6%pHB67&Xh<A8@
> z^gtcN$z?~Ex=I4F;&dg#{(o>H;vz>ei8GmBwT*x%6$zg8<8!I0{wTwiSn(y<`Mzb-
> z{*55W*pI;$vl40?nqHZ5FFQN{bWv$<Pm{FZzZvy!G)ITGn?M^w$ZS;fusK^Uh;s`U
> zoxRs*RK(fKq~fscP;GHGo4fY^6$0_gkl!HFQxA=v?dY$Ix8WBxlKRhY_kqV=7KBK^
> z?ONYNc6g)l;Z~7XW}3p(fyLGZwrR>vQ6&$0%*%oaWjF$l&E9L`&3nVJt40=w=gk}A
> z4nKETf(*i8!4#sP?!6H3(aIzts9zURyP+dO)gDqJ%O9+PMa~b5B-VN{)^ac%dzF=U
> zTNdz|^eV8^1Mbh|iw%|(x*`vcE$Tjb4GNrH^=s>ue&mW5Q|FIE%sD1%t-cmAk0srT
> zDSlPgs1OB()*|fM5*dm-DEEI1XO3u4Y<=6p+7V~^b}{%0>%S=DJ(<xGHmj*%ro=Rx
> zs7zchkA$+!6H5CyY(luS*C@>R&$_rx^fQJ2`<6baf4d75hWp#RtekV{;-9wo+)zE-
> zTnfc0$Wg=b=`($plLN6<#E;DaXS2(vxl9APjO3Qz@BjJjfnh0TnBBOz)4WCKf`;&X
> z{7pd1!4;LS+P)ukclqN^@n_(Njgihj@Y?6&`FNt2(-m?CFtz9JPi<U8A_e5Il#4&p
> zWu(53LxhrPY2Eki>>2OELZBx_2ddDP&2J9CV;Se%#MuTdjd&7JNR}+=6^lyrc1zy2
> zH=(2VoGd1<Hj;%;p6W;u$gKs71_<`yhy!W3jzTsq5bsVTzzeGYH;klg0yD3Nl^|cs
> zesk`jVo^#%4sN6l&cKK9la)>WZmbdxvdY6XDfnm~kNDUsrX@l4kUEGs&Vr7UwCb1Y
> zw%5^%3{f~v8sG}A|E3--71Jv3C|g<rOisc0OZzevLxbot><an@M>xYs+*<*(u(}T8
> zVC~noyV^9R^MP;LO?}+-bEEhx$%af}#ygl`Jlfs=_3aTp)H=3kFAK+1AwnU3dw+~d
> zeQBV#z=aIoa8;(<ssWeGmO#2L!{N7g*f206U(lt-*lkp$8trmh&7BD;KtuDOL94+U
> z8gJfqOsI1eEx0{IHE;#{Iv^IX(<w-TCjXe(P}QC{1`APkCo8Pki8nP1njHuQY)!Hz
> zMkOi%CUN4y^8lZvNKYZ?!kZ5kFfXd($H*vbp8jqFMHHQz`Pwxfv#gquSd0H)V8YET
> zHug=nG8RsPS&gh2FY(KbOiJg4eou@S>oVpiaB;A|i))BDkuQ2dt(XCp;1_Q|9O6aT
> znVb^MCD9Mzc%M<S3--#`M$L#Ea5}UiaVFs8w9xu4r{<9vl+m0M>gz);CJE%ojHTh%
> zN9t6*srSjMG)o&rI>{5stst0D=(6I9fDf{v8k@1C4Z2kOJ2UG8yozMr{UtEn{{8*2
> z<CY!0M1B`Zj-k%tmcODfeX^VW<mhASqEZR1K0o<tUo%~(d|5vJ(Ag^Rc_5yTCwlqg
> zLzn_!$_+)1#>g~_``M)k#_A%s11mPjQ$pob#ai>e1~_=1j}ITm6E`XCx1yyi5lcp)
> zPR@d9o;+}!nfM<w2pIPK9X9+K>rq>kl^o(}64@*i^e+eJM@JtTZN8Aj|CKEHqe}R2
> z`#(a+%8VzMnuw)gKvrO_)A82hOWyT+faX2~?&3XNl0&xlAZl->^NwK(mnEG_IyjwN
> zZV%9<>}}KMPyt0z8aiCTzJ=_{=yutz-gn5u3N<*!?(c#&D*C=}L$WfNr0D@Nb+31M
> zhrjAxB;sp7nBHM@-OAq#kf|1NHp(!z39l_e%^zD~2a(n8WaLBR?LagfK56^c*vsf0
> z>byVtaEbNy{(wW9+*w}SVQeqO_F`z?qTk*I#QOTOs$RbXMxsn4KN&2$&|JSn*@>){
> zuVz`cc&;d-OVpFhj@{}#fYuF)Od~JTmNfO_vlGmF4W`}i4gi8SNwbDzDR$Uth*ygK
> zR;-roKO0#-J4e*LeX&s=uT6=UlTTfGSa}c%p7}ET55`++*5{x^LhJJO*rHPqAsgY1
> z0b{Nz;*vtd;#LNUzHezZx=oC2ghLUMY1Q&{5$81WX(n8FQ~iQf73X<q%5DBu##v>m
> zZn#ShfwDz~)!kVxwj_MOrkPBkZ;AJGD9?%oYWs)NV&U-8izoLaX3}eNzfQA<#hD~S
> zl**rd*$P2XC>)!ehm1&;9V7N-thd$3J7+0+0U)_mb!zh{&|-peQ3{`HarqpX0+3*@
> z%$gRpZ|S&NH8tor<&5qBb}tP&>s#cnzllE)$anX{1?h|DrW?~C2z&YzIeD}4)g3Up
> zihNA&j{Bg5u2$x8&u4b6&&TueL@(a~FrQuae1tKE8k(ye(g&HQL`>Y!>eZVSn12M<
> zX$g6D<a|G-DgG=;%)t_C2O&zSp0%h-DFqlf;Bc?b2Y9`i{Z2H`f(DJxu>?q_%23Bm
> zz0F()g%7A8hvFqxsnLoz^CFh+Rd2Vvwu+Qu@)I%JC~F2@vYsGsCED3Kh#jCygHX6(
> zR}ZL0rhBdubN3gXOhu{i@m%D?uHZlBgm%w=pc-Eq{4t-Bv6N$5(J@zRsq7F-ks8NQ
> z4t|kigPvxlEg5K>{tgs&2qrWt{eFWY<8SD!+*Zq*wV0}*#rytXEsdn6XO4G(k{J7E
> zfCQWsNS_=BVy~okDAMJz>}Q(J*22I5wU<(xOv?Xl<d6)S84VGCi#d;Ph2aghq#-Tf
> z)Q)UzCQI<zcbFRQ1>|EHF1GA0Rm0k~)6Hp<2pSR}Dvmz`=#8UoC$>t}!`=$@E+70n
> z*bFn`NO>!uD%1slB>91Q$)XI6N#htR6(P7~5$fi%0}Kr_N$U_ie}B%ZF+N{z?U&be
> zzo=d1GH?rA8G-^wG}!}iRd)MzMPBq*nH(m8ZEmW%UVIwu(vXbjz#<r)n)+n@hmFJ8
> zc>)(DP34qbTnrM6K*ga;ot8Va>IJLlB&GUiWWbaZR5SS|%!OHqU;t}}Bl!dC(vGed
> zov4^+-B{wxJA~`o#NOU|tSut!F8Y?%GRBGPG8l}Jr8_W=nVS*PEmf#CKIQ!}7W1u7
> zBk^7YPW%7AsC^248!0Z;n8B^*$g{jMyB3DX(Ovr8!&~-0z%UONx5zwd`6-~{ler2%
> zaSI(Q{sZsp6!~_2T%@Eh#7LyhMuISM4V!2#T}rG%K}Y%XL^T|q;F4UD=i~W!qL)8B
> zfjL~7m$=4laI%kOePtgGv{H$(N6vdpwHD%Z6m}bX#4{zm$v2GyDC6*Q_G9hj5^_?Z
> zi*<hsIlB&CUKV3QsqN|bPb~_8VUihwVj68%E3jHd*Y%z^&boFEfvIHhnU|g>=Y?2&
> zkhy!;&SjrgPuH~vDuRaLP|!p&Ll$0I>JAlz(jVM^$<!;#Z5aDwf1$gdNsYgRt|cd2
> zQnJJgym876pBM84EhXNECl6&|J~f{uzk@~ZQN~$ht|d7`hJ7GFJjbh35z1%YVzjQU
> zO*?8M260QPA9;{a@pN7s5-gHjdDO4n;TeL1AmPQA1duQmTr*SG*R{Rhd27bxi_%$r
> zhsT@kPy6z+xGEilH1j=!dg|^1mB}>13N?cN)ex}=FU0_g9nCJzsM)Kyo{a|zVKEx#
> z@Fjb@kBvmVyPrj-CPEM@9NdaN8&~LklM;V)GBk`-AIZ2$K;vd3B|^k1tHcFY;=V&(
> z*XFv89SDv&A!PKdpBQdb05Gq&_Vsmz;ojI4TSp*i&IBq>reY{kc;}Ioez^1iYg-E+
> z0t&IvVf2JSrONzRd?L4$@hJ`<KB8Lxl}byB<c2Gb2opj&Bp1sOx5Nq7xN7-4q^Z2;
> zl;1>?6i-z^CRq&AZMM?il=KL}ye;DrxGjreGi7OFaWQd@Bp{M-7sLtgztQ=peIboY
> zl5odnPUE}%vW0;Jh=Ti3zUgpsM^G`CibJL+n%p-!jk{sdmsC3N!9@MAd$%-6R<tt&
> zExJDMr_=B6rf-2=q2D9^34xP8@^SyF2&a;@SZ0VoA7;TFUdty4lK*tSy~>47Jj17-
> zpBM?%H80&$xgcAq*KV2lJgH>Q#}mE$5dd@ex12BWyg2z-vX%)Ar~W&%F5$oF<Zr#f
> zOlu9-iopu*(#LISLKVotCFQ5-P@UBh9cME7k8zi}4~>eEXOK$`W{`*x$w*ZMbdVo=
> zQy)#lc!wM}>D^KEF4$dEkMeXcx9>WT0ZXm=AVvE}il=Z)c+#eMqIOKJQj055;?1zV
> zTHCs`VoYR*03w`6SWQ)<1h-w|WCDg60oOtba%5wKd&&+MYMJMzb5uMOfeR_fDOAEr
> z(AUyAsCwao1%?TTbCG=>Q=t9RBC*8uFr6Zn#Gi_9+q#{T<Jqfg^r36lGFneJR<kMN
> z*eDQcI-_v4HcF_Q&kX=$00{s!an=p`(@2%+G0?+q-E=6n=nU|-w910Bd5G4CLvf*E
> z2e^K9w-bMil6tr&ujm_WgDGc55$=B5Me4;I{KPV2G=1}ej1>4BY<)4{hisYAd<>lr
> zlr!Rvc41R?TqQVzBT=5>%%n1uzy<eZ<c$vV>qYnfudj>ljq$X*np}@<Y<wSx#S2+B
> zRm|#U2BLYa_lK33Zx*uAYke+K7ayCNiX2P5+5y22!^^>9MqI4oJTVh_*8-iLN5}57
> z99|U8cvPQ5P9qDco%^v%dmUMeXN;VJTl1@T$-y=J_ej!^!}MW?f~`Qi#7OmxfrMk^
> zmHZe1XYB26=sI+L(R*s%%yQUfxkJ{f;K{TAvzItwG^DajWs5Geb4<AT?(loeIpGG@
> zFrwkw)``Wl`}zR=SanK(3hd#zlNx6^(98Y@u`PE+#hW|e|JAWAKlrvEPZj<}M=pGU
> zI=BpSFK0B9CNua2mnBZ=mNFbmi#=c_pGI|YXx>fL2<}VnzekeYqvM4030<C#Cwlow
> zQ<%%i%Yot5Ong7B0+B*!7jLpak4Cx6rHmqci`}3}B-@_{>9)HhNhR6W`EQkh(q!U^
> z+yrdKp#6jl=C+Qyb!3e_%&8My<@?sj#V1Xhg6O`J=Ls0h(1>mxNgYbg_68#w!x(x5
> zbm^&fEwc{dHnFOvQ3c+|*TrMKh;7tV1jb+?5XxX>h?xhVaafy?baIHUy2c~OsZDF1
> zS!eT7UK#v_7*oHky}Gp=P2ku@t3Eto(}+QdB``kn1bIuB3wZF@vgsb)L=;33*H@rk
> zG0k*G{*SytHRAlbc+c*dbqq;%@DPFDFYBUwr(qKCe%~~ABKL#xvgjbD(r6l$uZ-!z
> zg8WbjRP<9Cm+Dz@mqEYi6YsT@s&snx%L@qPlEi28Ko2`?Zk9k6k-3V$M8n#xMqfO3
> zrmK$`oY17W0N2D4jet!{vC8XnSMd~{#WlO1q9g0(w%}yg(a5h~R<zaC-;5D2iF^+z
> z7@7`fZmQH@HFKTxYop`vUi@k)BuQM$bt7vS@wI>rIBHZM-B9?vtSur(@rKz$DXo(r
> zlF58Qfx78%u50H;38dJrF(32!Rh;BxXcO^G8N1}dCuTkuXHrDNy-qE!8q%gksdoU8
> zL+0?=I6hWa9OBUm>Dgj1DIFub)<;zmazw-Afmpyctcginy5m)<7n#H3Q}k3Him=TB
> zj+VB8a@lOc-Ae4HL2<|JxySlwG&Hv^RQ}t;3^qVJ9PmupVq4gYN7?x|C^z~4jb0)F
> z#LNYlZZ|Yhl%3BkQrQHv&XWr1vd?G`gU93!pv6!cbhS$2i}8-#&6j51?E$L|pS4KP
> zvV}#S*yZ_nqL-gAev!+eO9oq-M@<kzi?<m2%oT!=QXE+8&g=53mtZ<^MQJiGmY~W^
> z9Tc15F2&I(C@beps8VD60Qr3SS{06K!3fUJUJ`xdAw_5%iO%kM6|#p?3g22=lF9~x
> z_2`@4x5;a`c6JX1M3APO{}zj?)Ch<W4rP@u=}fH~LhxV0pS>o2e;EFXQBRcPTuLx8
> zPv4_;wp`8Pqfaa}QGyRBh$zCqjS3cpOMSo;sCMONHV%b$CA|$4r2>ScV5V^SpsXMZ
> z_2WRT5rXNQ7HL6q(v2EHkc%u{Fy3`fJ+{mkg@ph-g5U0aFQ8t=+0sx<e|=eQBd$DA
> zqBq?UHVPH;kR&bYONZyY^rrG+M!I>h^8u4Y#m8gVkyIrZJuBMUs68_Hh{!@YGAl!S
> z_`^>Ec*b=mFESE52TkiXa96PGumkrk-p~Bom)qu%e1IbR8^1lew=ILuQxZIUc-TyD
> zop~<^SxVNK{{8i3{r7*o{_?v1{`Sz_)vyWL|F+3bKoLliV4U!>F38x~w@W?U#%_5x
> zp-URjp?dJ?P<ng>o>A%eguA88D(d89|Efc`JsTefo3xHM^U}7M6htnv+Y0*?Ejj#X
> zY36rGxVITK`@|qsDDKlZwQet2Ouj%!nM3vYy6)wAzl;RaK97M7o_i{_7qj_FQauL8
> zR_GVk<I?f!jojX_B$LKOE>s8MNzh8e#-wpeL&nwnzHUGEwXXx^hEhu{1SkM-tbX{a
> z_#o?>biD0=zR)Y;$;h32C<yKqDE{;C%VF4ZDebrji2=nII_Unt+1%&3e&7-tcNko-
> zU(ZbGsiW@Ig%Zh`h%FI~?R?rM$^LHsRy===fH7y8O}GlRf^ID0R@Z-(he`BsPrZfz
> z!-whlc%qkoHh}q5zV8z3kV6DzGrEuL`5t_1+KDTp$?SLPhbDi(h#b}&?Y<I6W(XCF
> z7$}CL_LVZywQ98&`+)E_E2=y*H8w42*W5oR{EYGr+?!DhqxT$Ct4B{>RSXTVEf4Bm
> zz*&p0cHD<}z_KGo4HLD$yFYU!iLvXkgHyq-5=Pp_5?%I2Ro7ufo}!?=q<$YtfHYOZ
> z3T-U^sk{-VsboB5k^<{+TtrS(J*frMX_#(6u}wx*p(a|35mV;F=$G$CM6rH9kV)7l
> ztP6)cAZ`XKDDoZ7CLoUUBwXXFIvUw2C}`dv<}ij9KAwq5PIGfA`+H1j)SmTapfb+|
> z-$7#r^RfEF-qbe?bd>Q-pcwZe-yBAZ&K&lQZ8(m^kx8@a_woC&v6V1E+sGJTI-ImF
> zf!JA!bI$_E5$D(4>>J+-yG{958WPfn@O|la`+sbMC$_`jw7uFl>Td1Jl(KYli;nha
> zow`t3_OaX4x_-J@GLmM|*kx#YLzJ%bFw)MVX30Q_5GHk7B|79W+-f~-LNfJR=56Lk
> z*2=qa`ivYXaN+ajC#n>4Ia^O2lix<TO>pr$DYUVYs+1v~WDeKa^yP>Hn(QkMUFQRH
> z={Q9>(0~sk+FW+*tF%um-70M=%sK^lVoeIO00I2ADWA|)R|?a@NhIx5Npe3xfLQ$q
> zseaQDtz%PYHHp^?^6~9%V`uF42z0_k$ijj<g!qcjPo{aGTpDyylGr1xP3FAGA1^Wa
> z&t)2ZP6?Bbam&9zkO&{98NO^9>7uYST{3HHVA?Y(>h-}}j$fmBns4r=rChHaXTL|D
> z6%=353t+!2>+>TSEvNx;AYnC6b04-IwkLFXKA!01PXU+@#xGI@X%)`YDQryqUGTs`
> zN||qj^V-4ANU@bA2@J+~p%6N-lg%w}5g+057z$yGwF%2t1D*+|W8<d#!hyaWO3CJl
> z?{6N0*0mM)aE<cP?CUT43vDmB*{*(c&%8!LQeF!!xM|02(h@FeTx^%v^DY;Q_%LEj
> zq{5}}qcFWz54!-I+fdS>ytQL0F@rL*lVX{wN?+kJ{Hh+WA#0|i4rpfZmN(#F(Liai
> zmwGG#`4G_%ZFsN*Yn&fhLcANQHpc$Pr^Br)IB?kB$EE|8h7p;m)!`o<^OHl#qGe5L
> z{n@(XEv)S#w$iHeB^5_XT^Z$$s#D-%Jf<1q4QaI6UbNtTyAN=Z{0H+D=wrfH<LXs7
> zrLM7qnKl5DB;m>nTsvF#pS-L0(b&=vN3I@CoO&wtd$nt>TZL~Y33NN^KPEo3F$F*V
> z9&xC=X>biI`+xXmt!AoV=uuBm0dXsw@od!4s=c_?7K?2KBlz<D-v8sb_kX;uLABa^
> zHlg9=-IX~l(D<^9{prPM$0r5}tTmhO0dg4m(>(?vGqD!LxXR$4QHdvUrMoI4;f-GD
> zgT4nTj(FmbEkBdYhT|i`2d_~8s;HZNwXkJDyD(;n7k&f!H23k7lRX)GPnzj_Hmv$p
> z<H|i&@!6r^TKq<DrBaNIp=ZW!lFBZrG#emXnT5+?lb|zg(+Ffd&cn}y@M@2<*Im4A
> z$L=R*VB=v>?uLO&QP~AucJq}yF6vkh6}@yg@})M64i4GV+~cR@um8Aqg+C2L{9LpC
> zw;ipVcf~=8>-@~pcJMNSlVEM|0PG3xI@yURTrL(LszjF|hzA%Jwt}nON3rx?xv2KT
> zUuWv#Nz^2IqUvfE?Vl2K`+PhfPxSKFAQ>Y0juD|X9$I-q7VdU^XZS&#gzy~rIGV(b
> zOLN~l(*^lBg<*=Gzeu;7J;$n5Ym~Y89pHpXuw|(A_q&)CoWv1TMk;YZ1-p4Jz}CY*
> z*KBYwINI-!qu}<NboWw;z_D(TUBFOdt65HNMZF~tGo`ipJV6y1N;*n5d3Ae?iH+Xf
> z*YNGKCJ<s8`eA-Dw?(OW0B|#NrK8xfs(bt7v|OO8e0-zzgMca@12ngO?oE=Y0s+R7
> zDc6iX_g-6o8HM0cFhC-+GMosQOfTVq?xcKmibPJE<OoL~iH%mo_+8bkER@6{yVt{Q
> zL93(#lQ-T_%0s)qXo(vBdjn0W!)z}nVmCW4!eD`nnKO*ky7!4Sd(q+=!MlSvC+JJ=
> z8W&adc*45|CK^&w0HdL<BPRzQ14MHJn-Ewu&fzi6QbU6M9~%6(1fwh>$(7#)y@3|x
> z-BKM*o$sd}czVr0Pv3de7D7e_W9>ft*SE*M^}oEVAtH*S2}BBH3t1W){xOCUc~<PA
> zDVB?jI34$-vH-z4T8SVUqWm}bY(1x%32$0)GCZ&u6;7#1w}iCACqmxiwT#hX88W`-
> zwtx9v2gTie%hP0lrVddKC~6OxZ8TRinv$woP0r7kqDUpr*-v7TpUvYq*Hfy~lDM8R
> znhu16*UQ|-mXqNU)!a-<>jIly3ptpvZ|`}*5^Hbsd|MnZpz+_|H{6Ca@XAMn?jEVA
> z*o^F9RbS(bgZXCDB$`5U62+a+#V1TH`GN7v4{BHV13W_?OkjS>{O5n6%s6jMHcwlj
> zgz*%(awt(8-ehwyx0}uO+eEp=ItZW8-ANqz3dM&bCbWm0$)`+jJBylsclSZ%q9*g#
> z_v3}|9K1XqPxSJ$SCnZAGdXOeKUn%nd6HzS`UgR{U$D!_vm+z$z_PCArL0bknGQ~@
> z)}y33R-)pW%`JK&Ag`JrnPkFgY~$`b;L|W>ebI8OTSZH)+=1~X+om!SPgBtrxxfQJ
> ztUK6)8i#)Qvas{WNK?|A-x;}gF2fwlqCtwqFw#YVLPlmV%bcc-d2Rg$qYPc5)o<5h
> zbfZa#4}4HfP@|~i>dKyjGL}5x?Q~Zyyb(S`XGCU1%jR!6Tf$kJkNSSpyH$6A+fT^8
> zUHqe^-d>$!tf3jBR1A>=x=1mDJs{_*o7Xmf+B)Hwc7|Bo=3wRr5C}m`_|*D-n8y3z
> zYkyM>$xxGbNv^Z?%S{KO!4)bw=%mM`DXz#YmjOFP9nWx1j<+&>w}!NIuJ)S}2Ia#e
> z`~5MvE)TZZ1u{2^<CDd_JT~<TmtjfAmRyO+9s+a5yX_|)=6;XWviWS2+elyCpZ0od
> z_lE`B>;6Q#`8a!ekE6_0reae>;A)8MU0bgi8torn`1LlB(q=?DJ18#}4yxy~rNk&q
> z?M@~!yfg$b#5PUsku2G)R~n+JI_82FUpu2+V{#JGgr*$rfbJ+3i$m1&qgk^h+QG{m
> zNw&a0{twt~O%fF!2J%tCLdBL<_;8_Fh2(@XDYE_Ao(>Z<>jX;<&_!locU2J6?4e|B
> z>EfO-Wpuh7b3sAr!XgEtM9p`dLtijW+%YhmaT6Gd%Y12_XztCsTPE5ZFPa*(nJ@}=
> zi{?-taD{>k>L1+m2>np-<afczAAlw2U&+<4&ht09n!x;-(a_Htvz!55{NG$<Oy4{#
> zJ;4=k?ztD@dnvY}!P0~@(H9T21}4RQQjW>Sp$X?_3i=riGGFv}g=CJ~h5{$D3i2YY
> z;bw6eJfX|;@kB2_3%Lj#Fh!c$9t>zq1;ORAWS+ZwIi<DRk26=pQj;U6m_88PL)>Zl
> za?ZI*)a!o3P8seY_=O533E*ULuJc~%>;)MuqyFQ~h)kHM4ED|j=iH!w)FG1HOqE<a
> zFw-!@v2@G4!$9#b#T^*ju;F*+MGrX}Y6S4zmM^!(bOK#91>HOYoB>5`Q5j6B%e~+>
> z5uw(C{`~I8rQ4ywn1!o_WA1IHVrs;vxJhqE6<gAvj0qhGX47p`EJp&ok<ja(8&4YJ
> zZE!B6^RRmkT2%dX=iMB=&SZ{R6sE&#YiJ=VORthSRQ~lFc8tA-iOjxNw-+Rn?B|RI
> zk)ZUyt(GJciVJP<YuzjSzHi44By>;gPuU^Cs)oxiD~1)R$U>wBGesQus&5-<dM3Nt
> zl&hd2sL0m~78Z0S`w!uCeBX@Uh%wQABwmMPf4n_rHE^o~a)t<gbvENo#q=7s*cW{Q
> zjG>jVH&7oZwNQ-#1~zCAr@;+*)%nTrwD7v%wxB^iez1R&w?PGC$XfwmaE5?CiMD9>
> zYCyF{q+g?f+li$KU_*nC7<KB_Ei^YGP4_=L1`F2#Pozm_5#W}XB-hNSguw^O<V+Zg
> zvjrKo?zT*UoUtM7lL0yu{k0gKOFB7b2Zv=sA<osxo6XK_8l)enV)be*)9vHT#)mqg
> zHuRYJDZ9oiGxJ9)SN~N_FUQdF*xG7?rq_?T0mQQb9mk@^(>8!qy#MU?_pogs&z+PD
> zk8hz<k`A4dTx8B$=MSbUd}1qn0#x|)E1uTND^&SCY$M;B#{4f}75S9sHqYxP+`{v=
> z$CQHutGHDjAWF@ZN}qkYuyH4<Rf;elar*pqN`6D>GQ?~Xd^0nE>EeFK>1Sr{6on%p
> zQl{mU`qJm)`FNt2zrKBPjCvtYn9R5}q2ev3#ccC1K4PlSB5;UU$xGpBQ><>1s?lk3
> zzm2B2rK#{Wf2{KFL$=EiLIQG&iBMVViQ#>;>D!L_b;a$l`vf3^^UV9T#qHGE<cc@)
> z<F+E635eFFc+CvlL<u5;oGrH@vCt+^GZSQ@j<tIO8d<1Jx66b|hF`NwRHs^h@z}wI
> zmH$TRi%=^t6Yy{*x6I8`=>>L%R!M@p!hEnGt3swQh{!N<F}(yzqL}`Vg5zPMr$={l
> z1d+q(VYdy2eyJzwb8UA#xmU`v$f53xcy)sHmQLhi_ga%rOsK4$a=c?0D0Vc`ZZHqO
> zybKk`wi#hQ!b}ywwEZMl^foKHMUQc+j3EYihM-riZgtHz7Eq+2Pq<4D(G+EXAR<b2
> zu%r6vZ5yG1rbSV)%EJXM4>Or%C|uWD!?3FrO-Ohgzks)g(Vu>nTjGxIOm2@cp!G&~
> zjhY`gWMJ>6K`w(CcylH7>fpbj`nO@`*qIou03cZ`J=c^cJF#$aLF>{e6-2$rE!df3
> z`?H%GKeUm4sF-K0AcB_s7qw}Qc+<9|{d!Q|ae~L?Q!{zOHyMl1*5wRc;+gwz;gNtd
> zIeHLO1Ai(1vowY+KBZnhXQ;1iN2`%wm`64p^~-ry$yu9tmbH|T_l0@7qer(C^C=(Z
> z$%h$55Mx9xLp5hKz@H5)B&Ih7&s_AXalLo|Wluj$K74K*Lzx^J_+r=oz}!VH@Yjda
> z61sGCJMHSv%KfWh%SYHoP7v!OjP!Fs%jXb|KiE93PCtjP0GSU>muu7m|8AZm!V*Q#
> zxP@G1)=sVxap~1OZVN@ANzaL!VsL{)tQ#y4$O4aBABO1G4tdhWo{uMb`D^DeSN%D^
> z%W^gv(j?TXJwDtJIVmr0oaLhw$^gXK4=UOqLF%aWdJ52)s{dFlTQhVqmJZazv1nRh
> zicl1#&@3|a;v>_;878_o%8S6|jG$K$%`y+Ey&H>F|DHi0*~07#RsnDxY1!q(GPih-
> z**IXn&?&*jQWT7zg9t?mS5gUn3%piFTAvvE$YmkvxD|rb=7M1HMv<w;wP8%|n8eIQ
> z?{3D&Eg=nafj60RLVWf*^7I~cstwN{r{S$mw!wFXkUG-+lHwt=AgWCBBjaUrJX~tN
> z$<w)=qQ)oaQi{t;HVZmpZp*+|q+o`;5+2_X2HfL2Y^I(^{R($7or#g8wx0L8b|l6q
> zp-WG&WZ!AMyJ4D#$q#cxo{M!HoqE^ZC)z@OHi0A9s*a!#o9!pY8zx1!<z?i(s63-F
> zur6fHn0xF$e{`Ebl18mOmceY?-{-d4DZ1z-uOj;mYNcOa*B!uMd-rWv77I4m|M%^E
> zyQ>Kvxv*{j?bny}>um|&y!%#K3}X(X;WI<VP0;56$i?L3K`FXGx&o+f-k*mR11^%W
> zWB1c+-*6>xS`tXa$t~t)k<;49m_m!cwnaRfk>Ux_Qi+wyECDHV664eYmCL#VE!|B#
> zMD&=mB=Zc=!yg@uM9^)SkhjbT=7OfmK*q1!DnzEM>b7xBl@X|MC@sgzz$Avt7t%P;
> z{wW&RpB29}Q=?`J%Ci7MYT8Y%HrKqIBi!Q8=sWx|P`R{vBl=9CL8tKoe-E+z`H9Mz
> zUG`_n<`2Kayy#DkUZ<%`{G(AZE%l!UOvNBt8=%P)5I-l`-NM-2##g^vO;-_3ovil3
> z9-lLsI97(}mP#@Aud1!U$(Zssol8f`f*YV^$E;)yrA^rr$UGlU^zvs{rR%;(vJ{vL
> zY08t74UN=xSCFJ9=27FICPOecNm^Z5I|ZA#O9&bkVfxXS50eMHWE8<wo*N#?VrIB4
> zenIg?tuWG_y@e~dsCPtq({1!k_qX0_YU&Zgl6qXQS#F-S(He?rASjf}xc8<?TO5!q
> z9`^ukKs25WOHkRyX7<dBp~Iw{xW2;1TyV~b-401>G=0WvHTaJrV8M%co$7F9<-tNK
> zFi$_ETRI8Q4#8rtRSkXEnx$oA3|qj!3XzO{VT)gkbQ(CZ9_oSvdzgy_a~%z~d3Hxq
> zEMl^_O81C@$$ey3PPvfs=dtk7nTw0m+UU`LA7OgS(nl%m6+9AJQ0trHwz@OhmWGuu
> zvcq3*4e^&D9eJp;S@<#BN~DXkAcoZq-tA^YJ7Y|l%>$x}T#nM!kJuy`w*lr~L4k|J
> z^sJ)QXY96^exDYYF2r*2%Pal*SmA5@rpRMJ7bU`l(H35+V=<eLk@6(>&HVMt`fp!v
> zsOd4m@M)EO{NgI0g|i=lY@8)DPH>5C7(i*$VTXbU-tmmraIRZbTDHH*o08>}U?zZJ
> zRD>~8DrHr972HCZ7sR#vh%ll&&B%Ov?ScYjq)|<_Z|pwh?Dh;~CPjSVqHz%!VVCw*
> zUp=FExTL#yWamkYRw`Y|%I`2=iK8U>q{#!I!j;R4|FedfoXY%|j|fjS_-Q{JcEV?s
> z;iY`!)0^Yjn^->m?)-UM@br=&dH(-Mh%Z-PUcNUx`EG4+DY(D(Z06|<%*LS@bZH#Y
> zdLP}BwFGcW6q&s2+Ux)nil?sYB)S{D@B_P_CvLhtMK&F79A#zYX!%iziuSuLn59xP
> z-Ig#{Y+QUkGHEuD)#ZMC=Dj>0PxSJW<}Dxnip_8-AdRW3!^beACn(4dNw?-H%DTc2
> z;%UqS&(H&VM|oN1MwP+yG!10d#ueK{wY?ZGd>$G5-4!bN!Q1LO2x>z#Jdl7kv%jc)
> zuS)z4lYq|?0@l57UltDQl8r1$bFZ|NW@AB$%qCrkk<nolTV3TWRLprB{FFGN88m6p
> zrb&Bsi+#n~%qI1%V)Uy-#WhY+AGQH%9}KIduquw6$EeS$Y6w+h^H6Z|nE(}=rZ@_V
> zQI8r&|4WQsRc{ZqS8Y=xjaRSq^f>pVd)!Kyv{b&u!AYh&8!gadB|1k+Cmqv2s_)q$
> zS2R!2nkYYjtsl?<?Tj!+FN@&x$eEbdpfK!WgxQa|+{QL*8hdnsX#g8d|E5{;H_gNZ
> z)QRAfr7;(l(f+HKm64HxJQ!$Q6hbQ7stKP`dXz{uP73wf9$KA;)&L-M;kf9R9B;0w
> z`d+40jB{0|C4EN%@AvIZmG}GE4gg~_wBeRV?mS_}$E+jGUtX85BY3jLm|A}!3XTfk
> zBd$@wo(g@I$ZoeR9sM!ibT>gJ1XA4QQ7wyZtj?D#L_$vCMYUa0lW?)q%-x$Z21H7I
> zb?__0pWdf#Lil8CZbXiTMabKZi&Rm`A7oy&6swE1l+q28lkP;9HV48=De!srP;yRf
> zp7y6y&M@qfI`61OY&^gH0aGkKf|C-en=T#4s}(4Yz9+js3rG0-DUVaq$kk+nJ_!6h
> z><#`H3>?hxKjMIW_j^wN;52oR52PvbJ!dodxW#$#<4I3B^)YFVrH__qD6U|;6HAuc
> z>qW)@yR>T3n1w3!5YYo7@q9VVPGWpK=O@a5n^ji3LYwa~0%TOhsJ+hG)IeewB&I&4
> qlr+|xy9|5<lAn*~<MYRV3ornzP!%5^@m%Ks0000<MNUMnLSTaI1pSQw
> 
> literal 0
> HcmV?d00001
> 
> diff --git a/server/public/javascripts/cmwgapp.js b/server/public/javascripts/cmwgapp.js
> new file mode 100644
> index 0000000..77ae454
> --- /dev/null
> +++ b/server/public/javascripts/cmwgapp.js
> @@ -0,0 +1,249 @@
> +// Place your application-specific JavaScript functions and classes here
> +// This file is automatically included by javascript_include_tag :defaults
> +
> +function doPut(theNode)
> +{			
> +	$.ajax({
> +		  type: "PUT",
> +		  url: $(theNode.form).attr("action"),
> +		  data: $(theNode.form).serializeArray(),
> +		  success: function(returnData) {
> +			  alert("Command executed successfully!");
> +			  var flag = theNode.form.elements["refresh"];
> +			  if (flag != null && flag.value == "true") {
> +				  location.reload(true);
> +			  }
> +		  },
> +		  error: function(errorData) {
> +			  alert("Command executed unsuccessfully!")
> +		  },
> +		  dataType: "xml"
> +		});		
> +}
> +
> +function doXmlPut(theNode, addId, func)
> +{			
> +	var xmlData = "";
> +	if (func) {
> +		xmlData = fixupXml(theNode);
> +	}
> +	else {
> +		xmlData = "<?xml version='1.0' encoding='utf-8' ?>";
> +		xmlData += "<" + $(theNode.form).attr("xmlRootNode").value + " xmlns='http://www.dmtf.org/cimi'>";
> +		xmlData += getStandardData(theNode);	
> +		xmlData += "</" + $(theNode.form).attr("xmlRootNode").value + ">";
> +	}
> +	
> +	var padding = "";
> +	if (addId) {
> +		padding = "/" + $(theNode.form).attr("id").value;
> +	}
> +	
> +	$.ajax({
> +		  type: "PUT",
> +		  url: $(theNode.form).attr("action") + padding,
> +		  data: xmlData,
> +		  contentType: 'application/xml',
> +		  accepts: 'application/xml',
> +		  success: function(data, textStatus, jqXHR) {
> +			  alert("Command executed successfully!");
> +			  var flag = theNode.form.elements["refresh"];
> +			  if (flag != null && flag.value == "true") {
> +				  location.reload(true);
> +			  }
> +		  },
> +		  error: function(a, b, c) {
> +			  alert("Command executed unsuccessfully!")
> +		  },
> +		  statusCode: {
> +			204: function() {
> +				alert("Command executed successfully!")
> +			}  
> +		  },
> +		  dataType: "xml"
> +		});		
> +}
> +
> +function doXmlPost(theNode, func)
> +{		
> +	var xmlData = "";
> +	if (func) {
> +		xmlData = fixupXml(theNode);
> +	}
> +	else {
> +		xmlData = "<?xml version='1.0' encoding='utf-8' ?>";
> +		xmlData += "<" + $(theNode.form).attr("xmlRootNode").value + " xmlns='http://www.dmtf.org/cimi'>";
> +		xmlData += getStandardData(theNode)		
> +		xmlData += "</" + $(theNode.form).attr("xmlRootNode").value + ">";
> +	}
> +	
> +	$.ajax({
> +		  type: "POST",
> +		  url: $(theNode.form).attr("action"),
> +		  data: xmlData,
> +		  contentType: 'application/xml',
> +		  accepts: 'application/xml',
> +		  success: function(data, textStatus, jqXHR) {
> +			  alert("Command executed successfully!");
> +			  window.location.href = $(theNode.form).attr("refreshURI").value
> +		  },
> +		  error: function(jqXHR, data1, data2) {
> +			  alert("Command executed unsuccessfully!")
> +		  },
> +		  statusCode: {
> +			201: function() {
> +				alert("Command executed successfully!")
> +			}  
> +		  },
> +		  dataType: "xml"
> +		});		
> +}
> +
> +function doXmlDelete(theNode, addId)
> +{
> +	var xmlData = "<?xml version='1.0' encoding='utf-8' ?>";	
> +	var padding = "";
> +	if (addId) {
> +		padding = "/" + $(theNode.form).attr("id").value;
> +	}
> +	
> +	$.ajax({
> +		  type: "DELETE",
> +		  url: $(theNode.form).attr("action") + padding,
> +		  data: xmlData,		  
> +		  contentType: 'application/xml',
> +		  accepts: 'application/xml',
> +		  success: function(returnData) {
> +			  alert("Command executed successfully!")
> +			  //window.location.href = $(theNode.form).attr("action")
> +			  window.location.href = $(theNode.form).attr("refreshURI").value
> +		  },
> +		  error: function(errorData) {
> +			  alert("Command executed unsuccessfully!")
> +		  },
> +		  dataType: "xml"
> +		});		
> +}
> +
> +function getStandardData(theNode) {
> +	var xmlData = "";	
> +	xmlData += "<uri>" + $(theNode.form).attr("id").value + "</uri>\n";
> +	xmlData += "<name>" + $(theNode.form).attr("name").value + "</name>\n";
> +	xmlData += "<description>" + $(theNode.form).attr("description").value + "</description>\n";
> +	xmlData += "<created>" + $(theNode.form).attr("created").value + "</created>\n";
> +	
> +	//handling properties
> +	var index=0;
> +	while ($(theNode.form).attr("param_name_" + index)) {
> +		if ($(theNode.form).attr("param_name_" + index).value != null &&
> +				$(theNode.form).attr("param_name_" + index).value.length > 0) {
> +		  xmlData += "<property name='" + $(theNode.form).attr("param_name_" + index).value + "'>" + 
> +		                                 $(theNode.form).attr("param_value_" + index).value + "</property>\n";
> +		}
> +		index++;
> +	}	
> +		
> +	//handling operations
> +	index = 0
> +	while ($(theNode.form).attr("operation_" + index)) {
> +		var aOpNode = ttt0 = $(theNode.form).attr("operation_" + index);
> +		  xmlData += "<operation rel='" + $(aOpNode).attr("oper_type") + "' href='" + 
> +		                                 aOpNode.value + "' />\n";
> +		index++;
> +	}	
> +	
> +	return xmlData;
> +}
> +
> +function doDelete(theNode)
> +{
> +	var theURL = $(theNode.form).attr("action");
> +	var theData = $(theNode.form).serializeArray();
> +
> +	$.ajax({
> +		  type: "DELETE",
> +		  url: $(theNode.form).attr("action"),
> +		  data: $(theNode.form).serializeArray(),		  
> +		  success: function(returnData) {
> +			  alert("Command executed successfully!")
> +			  var flag = theNode.form.elements["refresh"];
> +			  if (flag != null && flag.value == "true") {
> +				  location.reload(true);
> +			  }
> +		  },
> +		  error: function(errorData) {
> +			  alert("Command executed unsuccessfully!")
> +		  },
> +		  dataType: "xml"
> +		});		
> +}
> +
> +function doPost(theNode)
> +{
> +	var theURL = $(theNode.form).attr("action");
> +	var theData = $(theNode.form).serializeArray();
> +	
> +	$.ajax({
> +		  type: "POST",
> +		  url: $(theNode.form).attr("action"),
> +		  data: $(theNode.form).serializeArray(),
> +		  success: function(returnData) {
> +			  alert("Command executed successfully!")
> +			  var flag = theNode.form.elements["refresh"];
> +			  if (flag != null && flag.value == "true") {
> +				  location.reload(true);
> +			  }
> +		  },
> +		  error: function(errorData) {
> +			  alert("Command executed unsuccessfully!")
> +		  },
> +		  dataType: "xml"
> +		});		
> +}
> +
> +function AddNewPproperty(tableId)
> +{
> +  var tbl = document.getElementById(tableId);
> +  var lastRow = tbl.rows.length;
> +  // if there's no header row in the table, then iteration = lastRow + 1
> +  var iteration = lastRow;
> +  var row = tbl.insertRow(lastRow);
> +  
> +  // left cell
> +  var cellLeft = row.insertCell(0);
> +  var el = document.createElement('input');
> +  el.type = 'text';
> +  el.name = 'param_name_' + iteration;
> +  el.id = 'param_name_' + iteration;
> +  el.size = 30;
> +  cellLeft.appendChild(el);
> +
> +  
> +  // right cell
> +  var cellRight = row.insertCell(1);
> +  var em = document.createElement('input');
> +  em.type = 'text';
> +  em.name = 'param_value_' + iteration;
> +  em.id = 'param_value_' + iteration;
> +  em.size = 30;
> +  cellRight.appendChild(em);
> +  
> +  // select cell
> +  var cellRightBut = row.insertCell(2);
> +  var er = document.createElement('input');
> +  er.type = 'button';
> +  er.name = 'param_remove' + iteration;
> +  er.id = 'param_remove' + iteration;
> +  er.value = "Remove";
> +  er.tableRow = row
> +  $(er).click(function() {
> +	removeProperty(this);	
> +  })
> +
> +  cellRightBut.appendChild(er);
> +}
> +
> +function removeProperty(theNode)
> +{
> +  $(theNode.parentNode.parentNode).remove();
> +}
> diff --git a/server/public/javascripts/jquery-1.4.2.min.js b/server/public/javascripts/jquery-1.4.2.min.js
> new file mode 100644
> index 0000000..7c24308
> --- /dev/null
> +++ b/server/public/javascripts/jquery-1.4.2.min.js
> @@ -0,0 +1,154 @@
> +/*!
> + * jQuery JavaScript Library v1.4.2
> + * http://jquery.com/
> + *
> + * Copyright 2010, John Resig
> + * Dual licensed under the MIT or GPL Version 2 licenses.
> + * http://jquery.org/license
> + *
> + * Includes Sizzle.js
> + * http://sizzlejs.com/
> + * Copyright 2010, The Dojo Foundation
> + * Released under the MIT, BSD, and GPL Licenses.
> + *
> + * Date: Sat Feb 13 22:33:48 2010 -0500
> + */
> +(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
> +e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
> +j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
> +"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
> +true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
> +Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
> +(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
> +a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
> +"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
> +function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
> +c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
> +L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
> +"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
> +a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
> +d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
> +a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
> +!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
> +true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
> +var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
> +parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
> +false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
> +s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
> +applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
> +else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
> +a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
> +w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
> +cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
> +i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
> +" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
> +this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
> +e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
> +c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
> +a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
> +function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
> +k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
> +C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
> +null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
> +e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
> +f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
> +if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
> +fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
> +d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
> +"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
> +a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
> +isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
> +{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
> +if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
> +e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
> +"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
> +d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
> +!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
> +toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
> +u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
> +function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
> +if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
> +e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
> +t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
> +g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
> +for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
> +1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
> +CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
> +relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
> +l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
> +h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
> +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
> +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
> +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
> +setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
> +h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
> +m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
> +"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
> +h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
> +!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
> +h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
> +q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
> +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
> +(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
> +function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
> +gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
> +c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
> +{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
> +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
> +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
> +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
> +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
> +a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
> +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
> +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
> +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
> +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
> +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
> +""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
> +this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
> +u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
> +1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
> +return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
> +""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
> +c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
> +c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
> +function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
> +Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
> +"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
> +a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
> +a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
> +"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
> +serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
> +function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
> +global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
> +e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
> +"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
> +false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
> +false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
> +c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
> +d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
> +g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
> +1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
> +"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
> +if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
> +this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
> +"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
> +animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
> +j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
> +this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
> +"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
> +c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
> +this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
> +this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
> +e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
> +c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
> +function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
> +this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
> +k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
> +f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
> +a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
> +c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
> +d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
> +f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
> +"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
> +e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
> diff --git a/server/server.rb b/server/server.rb
> deleted file mode 100644
> index 072e888..0000000
> --- a/server/server.rb
> +++ /dev/null
> @@ -1,1191 +0,0 @@
> -# Licensed to the Apache Software Foundation (ASF) under one or more
> -# contributor license agreements.  See the NOTICE file distributed with
> -# this work for additional information regarding copyright ownership.  The
> -# ASF licenses this file to you under the Apache License, Version 2.0 (the
> -# "License"); you may not use this file except in compliance with the
> -# License.  You may obtain a copy of the License at
> -#
> -#       http://www.apache.org/licenses/LICENSE-2.0
> -#
> -# Unless required by applicable law or agreed to in writing, software
> -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
> -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
> -# License for the specific language governing permissions and limitations
> -# under the License.
> -
> -require 'sinatra'
> -require 'deltacloud'
> -require 'json'
> -require 'sinatra/rack_accept'
> -require 'sinatra/static_assets'
> -require 'sinatra/rabbit'
> -require 'sinatra/lazy_auth'
> -require 'erb'
> -require 'haml'
> -require 'open3'
> -require 'sinatra/sinatra_verbose'
> -require 'sinatra/rack_driver_select'
> -require 'sinatra/rack_runtime'
> -require 'sinatra/rack_etag'
> -require 'sinatra/rack_date'
> -require 'sinatra/rack_matrix_params'
> -require 'sinatra/rack_syslog'
> -
> -set :version, '0.4.0'
> -
> -include Deltacloud::Drivers
> -set :drivers, Proc.new { driver_config }
> -
> -Sinatra::Application.register Rack::RespondTo
> -
> -use Rack::ETag
> -use Rack::Runtime
> -use Rack::MatrixParams
> -use Rack::DriverSelect
> -use Rack::MediaType
> -use Rack::Date
> -
> -configure do
> -  set :views, File.dirname(__FILE__) + '/views'
> -  set :public, File.dirname(__FILE__) + '/public'
> -  # Try to load the driver on startup to fail early if there are issues
> -  driver
> -end
> -
> -configure :production do
> -  use Rack::SyslogLogger
> -  disable :logging
> -  enable :show_errors
> -  set :dump_errors, false
> -  $stdout = SyslogFile.new
> -  $stderr = $stdout
> -end
> -
> -configure :development do
> -  # So we can just use puts for logging
> -  set :raise_errors => false
> -  set :show_exceptions, false
> -  $stdout.sync = true
> -  $stderr.sync = true
> -end
> -
> -# You could use $API_HOST environment variable to change your hostname to
> -# whatever you want (eg. if you running API behind NAT)
> -HOSTNAME=ENV['API_HOST'] ? ENV['API_HOST'] : nil
> -
> -error do
> -  report_error
> -end
> -
> -# Redirect to /api
> -get '/' do redirect root_url, 301; end
> -
> -get "#{Sinatra::UrlForHelper::DEFAULT_URI_PREFIX}\/?" do
> -  if params[:force_auth]
> -    return [401, 'Authentication failed'] unless driver.valid_credentials?(credentials)
> -  end
> -  @collections = [:drivers] + driver.supported_collections
> -  respond_to do |format|
> -    format.xml { haml :"api/show" }
> -    format.json do
> -      { :api => {
> -          :version => settings.version,
> -          :driver => driver_symbol,
> -          :links => entry_points.collect do |l|
> -            { :rel => l[0], :href => l[1] }.merge(json_features_for_entrypoint(l))
> -          end
> -        }
> -      }.to_json
> -    end
> -    format.html { haml :"api/show" }
> -  end
> -end
> -
> -# Rabbit DSL
> -
> -collection :drivers do
> -  global!
> -
> -  description <<EOS
> -List all the drivers supported by this server.
> -EOS
> -
> -  operation :index do
> -    description "List all drivers"
> -    control do
> -      @drivers = settings.drivers
> -      respond_to do |format|
> -        format.xml { haml :"drivers/index" }
> -        format.json { @drivers.to_json }
> -        format.html { haml :"drivers/index" }
> -      end
> -    end
> -  end
> -
> -  operation :show do
> -    description "Show details for a driver"
> -    param :id,      :string
> -    control do
> -      @name = params[:id].to_sym
> -      @driver = settings.drivers[@name]
> -      return [404, "Driver #{@name} not found"] unless @driver
> -      respond_to do |format|
> -        format.xml { haml :"drivers/show" }
> -        format.json { @driver.to_json }
> -        format.html { haml :"drivers/show" }
> -      end
> -    end
> -  end
> -end
> -
> -collection :realms do
> -  description <<END
> -  Within a cloud provider a realm represents a boundary containing resources.
> -  The exact definition of a realm is left to the cloud provider.
> -  In some cases, a realm may represent different datacenters, different continents,
> -  or different pools of resources within a single datacenter.
> -  A cloud provider may insist that resources must all exist within a single realm in
> -  order to cooperate. For instance, storage volumes may only be allowed to be mounted to
> -  instances within the same realm.
> -END
> -
> -  operation :index do
> -    description <<END
> -    Operation will list all available realms. Realms can be filtered using
> -    the "architecture" parameter.
> -END
> -    with_capability :realms
> -    param :id,            :string
> -    param :architecture,  :string,  :optional,  [ 'i386', 'x86_64' ]
> -    control { filter_all(:realms) }
> -  end
> -
> -  #FIXME: It always shows whole list
> -  operation :show do
> -    description 'Show an realm identified by "id" parameter.'
> -    with_capability :realm
> -    param :id,           :string, :required
> -    control { show(:realm) }
> -  end
> -
> -end
> -
> -collection :images do
> -  description <<END
> -  An image is a platonic form of a machine. Images are not directly executable,
> -  but are a template for creating actual instances of machines.
> -END
> -
> -  operation :new do
> -    description "Form to create a new image resource"
> -    param :instance_id, :string,  "An instance from which the new image will be created from"
> -    control do
> -      @instance = Instance.new( :id => params[:instance_id] )
> -      respond_to do |format|
> -        format.html { haml :"images/new" }
> -      end
> -    end
> -  end
> -
> -  operation :index do
> -    description <<END
> -    The images collection will return a set of all images
> -    available to the current use. Images can be filtered using the
> -    "owner_id" and "architecture" parameters.
> -END
> -    with_capability :images
> -    param :id,            :string
> -    param :architecture,  :string,  :optional
> -    control { filter_all(:images) }
> -  end
> -
> -  operation :show do
> -    description 'Show an image identified by "id" parameter.'
> -    with_capability :image
> -    param :id,           :string, :required
> -    control { show(:image) }
> -  end
> -
> -  operation :create do
> -    description 'Create image from instance'
> -    with_capability :create_image
> -    param :instance_id,	 :string, :required
> -    param :name,	 :string, :optional
> -    param :description,	 :string, :optional
> -    control do
> -      @image = driver.create_image(credentials, {
> -	:id => params[:instance_id],
> -        :name => params[:name],
> -	:description => params[:description]
> -      })
> -      status 201  # Created
> -      response['Location'] = image_url(@instance.id)
> -      respond_to do |format|
> -        format.xml  { haml :"images/show" }
> -        format.json { convert_to_json(:image, @image) }
> -        format.html { haml :"images/show" }
> -      end
> -    end
> -  end
> -
> -  operation :destroy do
> -    description "Remove specified image from collection"
> -    with_capability :destroy_image
> -    param :id,    :string,    :required
> -    control do
> -      driver.destroy_image(credentials, params[:id])
> -      status 204
> -      respond_to do |format|
> -        format.xml
> -        format.json
> -        format.html { redirect(images_url) }
> -      end
> -    end
> -  end
> -
> -end
> -
> -collection :instance_states do
> -  description "The possible states of an instance, and how to traverse between them "
> -
> -  operation :index do
> -    control do
> -      @machine = driver.instance_state_machine
> -      respond_to do |format|
> -        format.xml { haml :'instance_states/show', :layout => false }
> -        format.json do
> -          out = []
> -          @machine.states.each do |state|
> -            transitions = state.transitions.collect do |t|
> -              t.automatically? ? {:to => t.destination, :auto => 'true'} : {:to => t.destination, :action => t.action}
> -            end
> -            out << { :name => state, :transitions => transitions }
> -          end
> -          out.to_json
> -        end
> -        format.html { haml :'instance_states/show'}
> -        format.gv { erb :"instance_states/show" }
> -        format.png do
> -          # Trick respond_to into looking up the right template for the
> -          # graphviz file
> -          gv = erb(:"instance_states/show")
> -          png =  ''
> -          cmd = 'dot -Kdot -Gpad="0.2,0.2" -Gsize="5.0,8.0" -Gdpi="180" -Tpng'
> -          Open3.popen3( cmd ) do |stdin, stdout, stderr|
> -            stdin.write( gv )
> -            stdin.close()
> -            png = stdout.read
> -          end
> -          content_type 'image/png'
> -          png
> -        end
> -      end
> -    end
> -  end
> -end
> -
> -get "#{Sinatra::UrlForHelper::DEFAULT_URI_PREFIX}/instances/:id/run" do
> -  @instance = driver.instance(credentials, :id => params[:id])
> -  respond_to do |format|
> -    format.html { haml :"instances/run_command" }
> -  end
> -end
> -
> -collection :load_balancers do
> -  description "Load balancers"
> -
> -  operation :new do
> -    description "Form to create a new load balancer"
> -    control do
> -      @realms = driver.realms(credentials)
> -      @instances = driver.instances(credentials) if driver_has_feature?(:register_instance, :load_balancers)
> -      respond_to do |format|
> -        format.html { haml :"load_balancers/new" }
> -      end
> -    end
> -  end
> -
> -  operation :index do
> -    description "List of all active load balancers"
> -    control do
> -      filter_all :load_balancers
> -    end
> -  end
> -
> -  operation :show do
> -    description "Show details about given load balancer"
> -    param :id,  :string,  :required
> -    control { show :load_balancer }
> -  end
> -
> -  operation :create do
> -    description "Create a new load balancer"
> -    param :name,  :string,  :required
> -    param :realm_id,  :string,  :required
> -    param :listener_protocol,  :string,  :required, ['HTTP', 'TCP']
> -    param :listener_balancer_port,  :string,  :required
> -    param :listener_instance_port,  :string,  :required
> -    control do
> -      @load_balancer = driver.create_load_balancer(credentials, params)
> -      status 201  # Created
> -      response['Location'] = load_balancer_url(@instance.id)
> -      respond_to do |format|
> -        format.xml  { haml :"load_balancers/show" }
> -        format.json { convert_to_json(:load_balancer, @load_balancer) }
> -        format.html { haml :"load_balancers/show" }
> -      end
> -    end
> -  end
> -
> -  operation :register, :method => :post, :member => true do
> -    description "Add instance to loadbalancer"
> -    param :id,  :string,  :required
> -    param :instance_id, :string,  :required
> -    control do
> -      driver.lb_register_instance(credentials, params)
> -      status 204
> -      respond_to do |format|
> -        format.xml
> -        format.json
> -        format.html { redirect(load_balancer_url(params[:id])) }
> -      end
> -    end
> -  end
> -
> -  operation :unregister, :method => :post, :member => true do
> -    description "Remove instance from loadbalancer"
> -    param :id,  :string,  :required
> -    param :instance_id, :string,  :required
> -    control do
> -      driver.lb_unregister_instance(credentials, params)
> -      status 204
> -      respond_to do |format|
> -        format.xml
> -        format.json
> -        format.html { redirect(load_balancer_url(params[:id])) }
> -      end
> -    end
> -  end
> -
> -  operation :destroy do
> -    description "Destroy given load balancer"
> -    param :id,  :string,  :required
> -    control do
> -      driver.destroy_load_balancer(credentials, params[:id])
> -      status 204
> -      respond_to do |format|
> -        format.xml
> -        format.json
> -        format.html { redirect(load_balancers_url) }
> -      end
> -    end
> -  end
> -
> -end
> -
> -
> -collection :instances do
> -  description <<END
> -  An instance is a concrete machine realized from an image.
> -  The images collection may be obtained by following the link from the primary entry-point.
> -END
> -
> -  operation :new do
> -    description "Form for creating a new instance resource"
> -    param :image_id,  :string,  "Image from which will be the new instance created from"
> -    param :realm_id,  :string, :optional
> -    if driver_has_feature? :authentication_key
> -      param :authentication_key, :string, :optional
> -    end
> -    if driver_has_feature? :firewalls
> -      param :firewalls, :string, :optional
> -    end
> -    control do
> -      @instance = Instance.new( { :id=>params[:id], :image_id=>params[:image_id] } )
> -      @image   = Image.new( :id => params[:image_id] )
> -      @hardware_profiles = driver.hardware_profiles(credentials, :architecture => @image.architecture )
> -      @realms = [Realm.new(:id => params[:realm_id])] if params[:realm_id]
> -      @realms ||= driver.realms(credentials)
> -      @keys = driver.keys(credentials) if driver_has_feature?(:authentication_key)
> -      @firewalls = driver.firewalls(credentials) if driver_has_feature?(:firewalls)
> -      respond_to do |format|
> -        format.html do
> -          haml :'instances/new'
> -        end
> -      end
> -    end
> -  end
> -
> -  operation :index do
> -    description "List all instances."
> -    with_capability :instances
> -    param :id,            :string,  :optional
> -    param :state,         :string,  :optional
> -    control { filter_all(:instances) }
> -  end
> -
> -  operation :show do
> -    description 'Show an instance identified by "id" parameter.'
> -    with_capability :instance
> -    param :id,           :string, :required
> -    control { show(:instance) }
> -  end
> -
> -  operation :create do
> -    description "Create a new instance."
> -    with_capability :create_instance
> -    param :image_id,     :string, :required
> -    param :realm_id,     :string, :optional
> -    param :hwp_id,       :string, :optional
> -    control do
> -      @instance = driver.create_instance(credentials, params[:image_id], params)
> -      status 201  # Created
> -      response['Location'] = instance_url(@instance.id)
> -      respond_to do |format|
> -        format.xml  { haml :"instances/show" }
> -        format.json { convert_to_json(:instance, @instance) }
> -        format.html do
> -          redirect instance_url(@instance.id) if @instance and @instance.id
> -          redirect instances_url
> -        end
> -      end
> -    end
> -  end
> -
> -  operation :reboot, :method => :post, :member => true do
> -    description "Reboot a running instance."
> -    with_capability :reboot_instance
> -    param :id,           :string, :required
> -    control { instance_action(:reboot) }
> -  end
> -
> -  operation :start, :method => :post, :member => true do
> -    description "Start an instance."
> -    with_capability :start_instance
> -    param :id,           :string, :required
> -    control { instance_action(:start) }
> -  end
> -
> -  operation :stop, :method => :post, :member => true do
> -    description "Stop a running instance."
> -    with_capability :stop_instance
> -    param :id,           :string, :required
> -    control { instance_action(:stop) }
> -  end
> -
> -  operation :destroy do
> -    description "Destroy an instance."
> -    with_capability :destroy_instance
> -    param :id,           :string, :required
> -    control { instance_action(:destroy) }
> -  end
> -
> -  operation :run, :method => :post, :member => true do
> -    description <<END
> -  Run command on instance. Either password or private key must be send
> -  in order to execute command. Authetication method should be advertised
> -  in instance.
> -END
> -    with_capability :run_on_instance
> -    param :id,          :string,  :required
> -    param :cmd,         :string,  :required, [], "Shell command to run on instance"
> -    param :private_key, :string,  :optional, [], "Private key in PEM format for authentication"
> -    param :password,    :string,  :optional, [], "Password used for authentication"
> -    control do
> -      @output = driver.run_on_instance(credentials, params)
> -      respond_to do |format|
> -        format.xml { haml :"instances/run" }
> -        format.html { haml :"instances/run" }
> -      end
> -    end
> -  end
> -end
> -
> -collection :hardware_profiles do
> -  description <<END
> - A hardware profile represents a configuration of resources upon which a
> - machine may be deployed. It defines aspects such as local disk storage,
> - available RAM, and architecture. Each provider is free to define as many
> - (or as few) hardware profiles as desired.
> -END
> -
> -  operation :index do
> -    description "List of available hardware profiles."
> -    with_capability :hardware_profiles
> -    param :id,          :string
> -    param :architecture,  :string,  :optional,  [ 'i386', 'x86_64' ]
> -    control do
> -        @profiles = driver.hardware_profiles(credentials, params)
> -        respond_to do |format|
> -          format.xml  { haml :'hardware_profiles/index' }
> -          format.html  { haml :'hardware_profiles/index' }
> -          format.json { convert_to_json(:hardware_profile, @profiles) }
> -        end
> -    end
> -  end
> -
> -  operation :show do
> -    description "Show specific hardware profile."
> -    with_capability :hardware_profile
> -    param :id,          :string,    :required
> -    control do
> -      @profile =  driver.hardware_profile(credentials, params[:id])
> -      if @profile
> -        respond_to do |format|
> -          format.xml { haml :'hardware_profiles/show', :layout => false }
> -          format.html { haml :'hardware_profiles/show' }
> -          format.json { convert_to_json(:hardware_profile, @profile) }
> -        end
> -      else
> -        report_error(404)
> -      end
> -    end
> -  end
> -
> -end
> -
> -collection :storage_snapshots do
> -  description "Storage snapshots description here"
> -
> -  operation :new do
> -    description "A form to create a new storage snapshot"
> -    control do
> -      respond_to do |format|
> -        format.html { haml :"storage_snapshots/new" }
> -      end
> -    end
> -  end
> -
> -  operation :index do
> -    description "List of storage snapshots."
> -    with_capability :storage_snapshots
> -    param :id,            :string
> -    control { filter_all(:storage_snapshots) }
> -  end
> -
> -  operation :show do
> -    description "Show storage snapshot."
> -    with_capability :storage_snapshot
> -    param :id,          :string,    :required
> -    control { show(:storage_snapshot) }
> -  end
> -
> -  operation :create do
> -    description "Create a new snapshot from volume"
> -    with_capability :create_storage_snapshot
> -    param :volume_id, :string,  :required
> -    control do
> -      @storage_snapshot = driver.create_storage_snapshot(credentials, params)
> -      status 201  # Created
> -      response['Location'] = storage_snapshot_url(@storage_snapshot.id)
> -      show(:storage_snapshot)
> -    end
> -  end
> -
> -  operation :destroy do
> -    description "Delete storage snapshot"
> -    with_capability :destroy_storage_snapshot
> -    param :id,  :string,  :required
> -    control do
> -      driver.destroy_storage_snapshot(credentials, params)
> -      status 204
> -      respond_to do |format|
> -        format.xml
> -        format.json
> -        format.html { redirect(storage_snapshots_url) }
> -      end
> -    end
> -  end
> -end
> -
> -collection :storage_volumes do
> -  description "Storage volumes description here"
> -
> -  operation :new do
> -    description "A form to create a new storage volume"
> -    control do
> -      respond_to do |format|
> -        format.html { haml :"storage_volumes/new" }
> -      end
> -    end
> -  end
> -
> -  operation :index do
> -    description "List of storage volumes."
> -    with_capability :storage_volumes
> -    param :id,            :string
> -    control { filter_all(:storage_volumes) }
> -  end
> -
> -  operation :show do
> -    description "Show storage volume."
> -    with_capability :storage_volume
> -    param :id,          :string,    :required
> -    control { show(:storage_volume) }
> -  end
> -
> -  operation :create do
> -    description "Create a new storage volume"
> -    with_capability :create_storage_volume
> -    param :snapshot_id, :string,  :optional
> -    param :capacity,    :string,  :optional
> -    param :realm_id,    :string,  :optional
> -    control do
> -      @storage_volume = driver.create_storage_volume(credentials, params)
> -      status 201
> -      response['Location'] = storage_volume_url(@storage_volume.id)
> -      respond_to do |format|
> -        format.xml  { haml :"storage_volumes/show" }
> -        format.html { haml :"storage_volumes/show" }
> -        format.json { convert_to_json(:storage_volume, @storage_volume) }
> -      end
> -    end
> -  end
> -
> -  operation :attach, :method => :post, :member => true do
> -    description "Attach storage volume to instance"
> -    with_capability :attach_storage_volume
> -    param :id,         :string,  :required
> -    param :instance_id,:string,  :required
> -    param :device,     :string,  :required
> -    control do
> -      @storage_volume = driver.attach_storage_volume(credentials, params)
> -      status 202
> -      respond_to do |format|
> -        format.html { redirect(storage_volume_url(params[:id]))}
> -        format.xml  { haml :"storage_volumes/show" }
> -        format.json { convert_to_json(:storage_volume, @storage_volume) }
> -      end
> -    end
> -  end
> -
> -  operation :detach, :method => :post, :member => true do
> -    description "Detach storage volume to instance"
> -    with_capability :detach_storage_volume
> -    param :id,         :string,  :required
> -    control do
> -      volume = driver.storage_volume(credentials, :id => params[:id])
> -      @storage_volume =  driver.detach_storage_volume(credentials, :id => volume.id, :instance_id => volume.instance_id, :device => volume.device)
> -      status 202
> -      respond_to do |format|
> -        format.html { redirect(storage_volume_url(params[:id]))}
> -        format.xml  { haml :"storage_volumes/show" }
> -        format.json { convert_to_json(:storage_volume, @storage_volume) }
> -      end
> -    end
> -  end
> -
> -  operation :destroy do
> -    description "Destroy storage volume"
> -    with_capability :destroy_storage_volume
> -    param :id,          :string,  :optional
> -    control do
> -      driver.destroy_storage_volume(credentials, params)
> -      status 204
> -      respond_to do |format|
> -        format.xml
> -        format.json
> -        format.html { redirect(storage_volumes_url) }
> -      end
> -    end
> -  end
> -
> -end
> -
> -collection :keys do
> -  description "Instance authentication credentials."
> -
> -  operation :new do
> -    description "A form to create a new key resource"
> -    control do
> -      respond_to do |format|
> -        format.html { haml :"keys/new" }
> -      end
> -    end
> -  end
> -
> -  operation :index do
> -    description "List all available credentials which could be used for instance authentication."
> -    with_capability :keys
> -    control do
> -      filter_all :keys
> -    end
> -  end
> -
> -  operation :show do
> -    description "Show details about given instance credential."
> -    with_capability :key
> -    param :id,  :string,  :required
> -    control { show :key }
> -  end
> -
> -  operation :create do
> -    description "Create a new instance credential if backend supports this."
> -    with_capability :create_key
> -    param :name,  :string,  :required
> -    control do
> -      @key = driver.create_key(credentials, { :key_name => params[:name] })
> -      status 201
> -      response['Location'] = key_url(@key.id)
> -      respond_to do |format|
> -        format.xml  { haml :"keys/show", :ugly => true }
> -        format.html { haml :"keys/show" }
> -        format.json { convert_to_json(:key, @key)}
> -      end
> -    end
> -  end
> -
> -  operation :destroy do
> -    description "Destroy given instance credential if backend supports this."
> -    with_capability :destroy_key
> -    param :id,  :string,  :required
> -    control do
> -      driver.destroy_key(credentials, { :id => params[:id]})
> -      status 204
> -      respond_to do |format|
> -        format.xml
> -        format.json
> -        format.html { redirect(keys_url) }
> -      end
> -    end
> -  end
> -
> -end
> -
> -#get html form for creating a new blob
> -
> -# The URL for getting the new blob form for the HTML UI looks like the URL
> -# for getting the details of an existing blob. To make collisions less
> -# likely, we use a name for the form that will rarely be the name of an
> -# existing blob
> -NEW_BLOB_FORM_ID = "new_blob_form_d15cfd90"
> -
> -get "#{Sinatra::UrlForHelper::DEFAULT_URI_PREFIX}/buckets/:bucket/#{NEW_BLOB_FORM_ID}" do
> -  @bucket_id = params[:bucket]
> -  respond_to do |format|
> -    format.html {haml :"blobs/new"}
> -  end
> -end
> -
> -collection :buckets do
> -  description "Cloud Storage buckets - aka buckets|directories|folders"
> -
> -  collection :blobs do
> -    description "Blobs associated with given bucket"
> -
> -    operation :show do
> -      description "Display blob"
> -      control do
> -        @blob = driver.blob(credentials, { :id => params[:blob], 'bucket' => params[:bucket]})
> -        if @blob
> -          respond_to do |format|
> -            format.xml { haml :"blobs/show" }
> -            format.html { haml :"blobs/show" }
> -            format.json { convert_to_json(:blob, @blob) }
> -          end
> -        else
> -          report_error(404)
> -        end
> -      end
> -
> -    end
> -
> -    operation :create do
> -      description "Create new blob"
> -      control do
> -        bucket_id = params[:bucket]
> -        blob_id = params['blob_id']
> -        blob_data = params['blob_data']
> -        user_meta = {}
> -        #metadata from params (i.e., passed by http form post, e.g. browser)
> -        max = params[:meta_params]
> -        if(max)
> -          (1..max.to_i).each do |i|
> -            key = params[:"meta_name#{i}"]
> -            key = "HTTP_X_Deltacloud_Blobmeta_#{key}"
> -            value = params[:"meta_value#{i}"]
> -            user_meta[key] = value
> -          end
> -        end
> -        @blob = driver.create_blob(credentials, bucket_id, blob_id, blob_data, user_meta)
> -        respond_to do |format|
> -          format.xml { haml :"blobs/show" }
> -          format.html { haml :"blobs/show"}
> -        end
> -      end
> -    end
> -
> -    operation :destroy do
> -      description "Destroy given blob"
> -      control do
> -        bucket_id = params[:bucket]
> -        blob_id = params[:blob]
> -        driver.delete_blob(credentials, bucket_id, blob_id)
> -        status 204
> -        respond_to do |format|
> -          format.xml
> -          format.json
> -          format.html { redirect(bucket_url(bucket_id)) }
> -        end
> -      end
> -    end
> -
> -    operation :stream, :member => true, :standard => true, :method => :put do
> -      description "Stream new blob data into the blob"
> -      control do
> -        if(env["BLOB_SUCCESS"]) #ie got a 200ok after putting blob
> -          content_type = env["CONTENT_TYPE"]
> -          content_type ||=  ""
> -          @blob = driver.blob(credentials, {:id => params[:blob],
> -                                            'bucket' => params[:bucket]})
> -          respond_to do |format|
> -            format.xml { haml :"blobs/show" }
> -            format.html { haml :"blobs/show" }
> -            format.json { convert_to_json(:blob, @blob) }
> -          end
> -        elsif(env["BLOB_FAIL"])
> -          report_error(500) #OK?
> -        else # small blobs - < 112kb dont hit the streaming monkey patch - use 'normal' create_blob
> -          # also, if running under webrick don't hit the streaming patch (Thin specific)
> -          bucket_id = params[:bucket]
> -          blob_id = params[:blob]
> -          temp_file = Tempfile.new("temp_blob_file")
> -          temp_file.write(env['rack.input'].read)
> -          temp_file.flush
> -          content_type = env['CONTENT_TYPE'] || ""
> -          blob_data = {:tempfile => temp_file, :type => content_type}
> -          user_meta = BlobHelper::extract_blob_metadata_hash(request.env)
> -          @blob = driver.create_blob(credentials, bucket_id, blob_id, blob_data, user_meta)
> -          temp_file.delete
> -          respond_to do |format|
> -            format.xml { haml :"blobs/show" }
> -            format.html { haml :"blobs/show"}
> -          end
> -        end
> -      end
> -    end
> -
> -    operation :metadata, :member => true, :standard => true, :method => :head do
> -      description "Get blob metadata"
> -      control do
> -        @blob_id = params[:blob]
> -        @blob_metadata = driver.blob_metadata(credentials, {:id => params[:blob], 'bucket' => params[:bucket]})
> -        if @blob_metadata
> -          @blob_metadata.each do |k,v|
> -            headers["X-Deltacloud-Blobmeta-#{k}"] = v
> -          end
> -          status 204
> -          respond_to do |format|
> -            format.xml
> -            format.json
> -          end
> -        else
> -          report_error(404)
> -        end
> -      end
> -    end
> -
> -    operation :update, :member => true, :method => :post do
> -      description "Update blob metadata"
> -      control do
> -        meta_hash = BlobHelper::extract_blob_metadata_hash(request.env)
> -        success = driver.update_blob_metadata(credentials, {'bucket'=>params[:bucket], :id =>params[:blob], 'meta_hash' => meta_hash})
> -        if(success)
> -          meta_hash.each do |k,v|
> -            headers["X-Deltacloud-Blobmeta-#{k}"] = v
> -          end
> -          status 204
> -          respond_to do |format|
> -            format.xml
> -            format.json
> -          end
> -        else
> -          report_error(404) #FIXME is this the right error code?
> -        end
> -      end
> -    end
> -
> -    operation :content, :member => true, :method => :get do
> -      description "Download blob content"
> -      control do
> -        @blob = driver.blob(credentials, { :id => params[:blob], 'bucket' => params[:bucket]})
> -        if @blob
> -          params['content_length'] = @blob.content_length
> -          params['content_type'] = @blob.content_type
> -          params['content_disposition'] = "attachment; filename=#{@blob.id}"
> -          BlobStream.call(env, credentials, params)
> -        else
> -          report_error(404)
> -        end
> -      end
> -    end
> -
> -  end
> -
> -  operation :new do
> -    description "A form to create a new bucket resource"
> -    control do
> -      respond_to do |format|
> -        format.html { haml :"buckets/new" }
> -      end
> -    end
> -  end
> -
> -  operation :index do
> -    description "List buckets associated with this account"
> -    with_capability :buckets
> -    param :id,        :string
> -    param :name,      :string
> -    param :size,      :string
> -    control { filter_all(:buckets) }
> -  end
> -
> -  operation :show do
> -    description "Show bucket"
> -    with_capability :bucket
> -    param :id,        :string
> -    control { show(:bucket) }
> -  end
> -
> -  operation :create do
> -    description "Create a new bucket (POST /api/buckets)"
> -    with_capability :create_bucket
> -    param :name,      :string,    :required
> -    control do
> -      @bucket = driver.create_bucket(credentials, params[:name], params)
> -      status 201
> -      response['Location'] = bucket_url(@bucket.id)
> -      respond_to do |format|
> -        format.xml  { haml :"buckets/show" }
> -        format.json { convert_to_json(:bucket, @bucket) }
> -        format.html do
> -          redirect bucket_url(@bucket.id) if @bucket and @bucket.id
> -          redirect buckets_url
> -        end
> -      end
> -    end
> -  end
> -
> -  operation :destroy do
> -    description "Delete a bucket by name - bucket must be empty"
> -    with_capability :delete_bucket
> -    param :id,    :string,    :required
> -    control do
> -      driver.delete_bucket(credentials, params[:id], params)
> -      status 204
> -      respond_to do |format|
> -        format.xml
> -        format.json
> -        format.html {  redirect(buckets_url) }
> -      end
> -    end
> -  end
> -
> -end
> -
> -get "#{Sinatra::UrlForHelper::DEFAULT_URI_PREFIX}/addresses/:id/associate" do
> -  @instances = driver.instances(credentials)
> -  @address = Address::new(:id => params[:id])
> -  respond_to do |format|
> -    format.html { haml :"addresses/associate" }
> -  end
> -end
> -
> -collection :addresses do
> -  description "Manage IP addresses"
> -
> -  operation :index do
> -    description "List IP addresses assigned to your account."
> -    with_capability :addresses
> -    control do
> -      filter_all :addresses
> -    end
> -  end
> -
> -  operation :show do
> -    description "Show details about IP addresses specified by given ID"
> -    with_capability :address
> -    param :id,  :string,  :required
> -    control { show :address }
> -  end
> -
> -  operation :create do
> -    description "Acquire a new IP address for use with your account."
> -    with_capability :create_address
> -    control do
> -      @address = driver.create_address(credentials, {})
> -      status 201    # Created
> -      response['Location'] = address_url(@address.id)
> -      respond_to do |format|
> -        format.xml  { haml :"addresses/show", :ugly => true }
> -        format.html { haml :"addresses/_address", :layout => false }
> -        format.json { convert_to_json(:address, @address) }
> -      end
> -    end
> -  end
> -
> -  operation :destroy do
> -    description "Release an IP address associated with your account"
> -    with_capability :destroy_address
> -    param :id,  :string,  :required
> -    control do
> -      driver.destroy_address(credentials, { :id => params[:id]})
> -      status 204
> -      respond_to do |format|
> -        format.xml
> -        format.json
> -        format.html { redirect(addresses_url) }
> -      end
> -    end
> -  end
> -
> -  operation :associate, :method => :post, :member => true do
> -    description "Associate an IP address to an instance"
> -    with_capability :associate_address
> -    param :id, :string, :required
> -    param :instance_id, :string, :required
> -    control do
> -      driver.associate_address(credentials, { :id => params[:id], :instance_id => params[:instance_id]})
> -      status 202   # Accepted
> -      respond_to do |format|
> -        format.xml
> -        format.json
> -        format.html { redirect(address_url(params[:id])) }
> -      end
> -    end
> -  end
> -
> -  operation :disassociate, :method => :post, :member => true do
> -    description "Disassociate an IP address from an instance"
> -    with_capability :associate_address
> -    param :id, :string, :required
> -    control do
> -      driver.disassociate_address(credentials, { :id => params[:id] })
> -      status 202   # Accepted
> -      respond_to do |format|
> -        format.xml
> -        format.json
> -        format.html { redirect(address_url(params[:id])) }
> -      end
> -    end
> -  end
> -
> -end
> -
> -#delete a firewall rule
> -delete '/api/firewalls/:firewall/:rule' do
> -  opts = {}
> -  opts[:firewall] = params[:firewall]
> -  opts[:rule_id] = params[:rule]
> -  driver.delete_firewall_rule(credentials, opts)
> -  status 204
> -  respond_to do |format|
> -    format.xml
> -    format.json
> -    format.html {redirect firewall_url(params[:firewall])}
> -  end
> -end
> -
> -#FIREWALLS
> -collection :firewalls do
> -  description "Allow user to define firewall rules for an instance (ec2 security groups) eg expose ssh access [port 22, tcp]."
> -
> -  operation :new do
> -    description "A form to create a new firewall resource"
> -    control do
> -      respond_to do |format|
> -        format.html { haml :"firewalls/new" }
> -      end
> -    end
> -  end
> -
> -  operation :new_rule, :form => true, :member => true, :method => :get do
> -    description "A form to create a new firewall rule"
> -    param :id,  :string,  :required
> -    control do
> -      @firewall_name = params[:id]
> -      respond_to do |format|
> -        format.html {haml :"firewalls/new_rule" }
> -      end
> -    end
> -  end
> -
> -  operation :index do
> -    description 'List all firewalls'
> -    with_capability :firewalls
> -    control { filter_all(:firewalls) }
> -  end
> -
> -  operation :show do
> -    description 'Show details for a specific firewall - list all rules'
> -    with_capability :firewall
> -    param :id,            :string,    :required
> -    control { show(:firewall) }
> -  end
> -
> -  operation :create do
> -    description 'Create a new firewall'
> -    with_capability :create_firewall
> -    param :name,          :string,    :required
> -    param :description,   :string,    :required
> -    control do
> -      @firewall = driver.create_firewall(credentials, params )
> -      status 201  # Created
> -      response['Location'] = firewall_url(@firewall.id)
> -      respond_to do |format|
> -        format.xml  { haml :"firewalls/show" }
> -        format.html { haml :"firewalls/show" }
> -        format.json { convert_to_json(:firewall, @firewall) }
> -      end
> -    end
> -  end
> -
> -  operation :destroy do
> -    description 'Delete a specified firewall - error if firewall has rules'
> -    with_capability :delete_firewall
> -    param :id,            :string,    :required
> -    control do
> -      driver.delete_firewall(credentials, params)
> -      status 204
> -      respond_to do |format|
> -        format.xml
> -        format.json
> -        format.html {  redirect(firewalls_url) }
> -      end
> -    end
> -  end
> -
> -  #create a new firewall rule - POST /api/firewalls/:firewall/rules
> -  operation :rules, :method => :post, :member => true do
> -    description 'Create a new firewall rule for the specified firewall'
> -    param :id,  :required, :string, [],  "Name of firewall in which to apply this rule"
> -    param :protocol,  :required, :string, ['tcp','udp','icmp'], "Transport layer protocol for the rule"
> -    param :port_from, :required, :string, [], "Start of port range for the rule"
> -    param :port_to,   :required, :string, [], "End of port range for the rule"
> -    with_capability :create_firewall_rule
> -    control do
> -      #source IPs from params
> -      addresses =  params.inject([]){|result,current| result << current.last unless current.grep(/^ip[-_]address/i).empty?; result}
> -      #source groups from params
> -      groups = {}
> -      max_groups  = params.select{|k,v| k=~/^group/}.size/2
> -      for i in (1..max_groups) do
> -        groups.merge!({params["group#{i}"]=>params["group#{i}owner"]})
> -      end
> -      params['addresses'] = addresses
> -      params['groups'] = groups
> -      if addresses.empty? && groups.empty?
> -        raise Deltacloud::Validation::Failure.new(nil, "No sources. Specify at least one source ip_address or group")
> -      end
> -      driver.create_firewall_rule(credentials, params)
> -      @firewall = driver.firewall(credentials, {:id => params[:id]})
> -      status 201
> -      respond_to do |format|
> -        format.xml  { haml :"firewalls/show" }
> -        format.html { haml :"firewalls/show" }
> -        format.json { convert_to_json(:firewall, @firewall) }
> -      end
> -    end
> -  end
> -
> -end
> diff --git a/server/tests/common.rb b/server/tests/common.rb
> index 71f1442..ae44869 100644
> --- a/server/tests/common.rb
> +++ b/server/tests/common.rb
> @@ -15,6 +15,7 @@
> #
> 
> $:.unshift File.join(File.dirname(__FILE__), '..')
> +$top_srcdir = File::dirname(File::dirname(__FILE__))
> 
> require 'rubygems'
> require 'yaml'
> @@ -25,7 +26,7 @@ require 'json'
> require 'digest/sha1'
> require 'base64'
> require 'rack/test'
> -require 'server'
> +require 'deltacloud/server'
> 
> driver
> 
> diff --git a/server/views/cimi/cloudEntryPoint/index.html.haml b/server/views/cimi/cloudEntryPoint/index.html.haml
> new file mode 100644
> index 0000000..9402e95
> --- /dev/null
> +++ b/server/views/cimi/cloudEntryPoint/index.html.haml
> @@ -0,0 +1,7 @@
> +
> +- @allAPIs.each do |api|
> +  - if api != :cloudEntryPoint
> +    - newName = api.to_s.pluralize
> +    - newName = newName.gsub(/[A-Z]/, ' \0')
> +    %a{ :href => '/api/collection/'+api.to_s }= newName.capitalize + '<br/>'
> +  
> diff --git a/server/views/cimi/cloudEntryPoint/index.xml.haml b/server/views/cimi/cloudEntryPoint/index.xml.haml
> new file mode 100644
> index 0000000..878e5ec
> --- /dev/null
> +++ b/server/views/cimi/cloudEntryPoint/index.xml.haml
> @@ -0,0 +1,10 @@
> +!!!XML
> +%CloudEntryPoint{ :xmlns => CMWG_NAMESPACE }
> +  %uri=HOST_API_PATH + "/cloudEntryPoint"
> +  %name cloud entry point
> +  %description cloud entry point
> +  %created= Time.new.getutc.to_s
> +  - @allAPIs.each do |api|
> +    - if api != :cloudEntryPoint
> +      = "<#{api.to_s.pluralize} href=\"#{HOST_API_PATH + "/collection/" +api.to_s} \"/>"
> +  %operation{ :rel => "edit", :href => HOST_API_PATH + "/cloudEntryPoint" }
> diff --git a/server/views/cimi/collection/index.html.haml b/server/views/cimi/collection/index.html.haml
> new file mode 100644
> index 0000000..fc45357
> --- /dev/null
> +++ b/server/views/cimi/collection/index.html.haml
> @@ -0,0 +1,74 @@
> +- newName = @dmtfitem["uri"] + " Collection"
> +- newName = newName.gsub(/[A-Z]/, ' \0')
> +%h1 #{newName.capitalize}
> +
> +%form{ :action => HOST_API_PATH + "/collection/" + @dmtfitem["uri"] }
> +  %input{ :name => :id, :type => :hidden, :value => @dmtfitem["uri"] }/
> +  %input{ :name => :xmlRootNode, :type => :hidden, :value => @xmlRootNode }/
> +  %p
> +    %label
> +      Name:
> +  %p
> +    %input{ :name => :name, :size => 50, :value => @dmtfitem["name"], :style => "width:50%;" }
> +    %input{ :name => :created, :type => :hidden, :size => 50, :value => @dmtfitem["created"] }
> +  %p
> +  %br
> +    %label
> +      Description:
> +  %p
> +    %textarea{ :name => :description, :cols => 50, :rows => 4, :style => "width:50%;" } #{@dmtfitem['description']}       
> +  %p
> +  %br
> +    %label
> +      Properties:      
> +  %p
> +    %table{ :style => "width:50%;", :id => "propertyTable"}
> +      - if @dmtfitem["property"]
> +        - if @dmtfitem["property"]["name"] && @dmtfitem["property"]["content"] 
> +          - newPropertyObj = {"#{@dmtfitem['property']['name']}" => {"content" => @dmtfitem["property"]["content"]}}
> +        - else
> +          - newPropertyObj = @dmtfitem["property"]
> +          
> +        - iter = -1
> +        - newPropertyObj.each_pair do |key, value|
> +          - iter += 1
> +          %tr
> +            %td
> +              %input{ :name => "param_name_" + iter.to_s, :size => 30, :value => key }                
> +            %td
> +              %input{ :name => "param_value_" + iter.to_s, :size => 30, :value => value["content"] }
> +            %td
> +              %input{ :type => :button, :value => "Remove", :onClick => "return removeProperty(this)" }
> +    %input{ :type => :button, :name => "commit", :value => "Add new property", :onClick => "return AddNewPproperty('propertyTable')" }
> +  %p 
> +    - if @dmtfitem["operation"]
> +      - if @dmtfitem["operation"].kind_of? (Array)
> +        - newPropertyObj = @dmtfitem["operation"]
> +      - else
> +        - newPropertyObj = [@dmtfitem["operation"]]
> +      - iter = -1
> +      - newPropertyObj.map do | operation|
> +        - iter += 1 
> +        %br
> +        %label
> +          = operation["rel"].capitalize + ":&nbsp;" + HOST_API_PATH + operation["href"]
> +          %input{ :name => "operation_"+iter.to_s, :oper_type => operation["rel"], :type => :hidden, :value => operation["href"] }       
> +  %br
> +  %input{ :type => :button, :name => "commit", :value => "Submit changes", :onClick => "return doXmlPut(this)" }/
> +  %input{ :name => "refresh", :value => false, :type => :hidden}
> +              
> +%p
> +%br
> +- newName = @dmtfitem["uri"]    
> +- newName = newName.gsub(/[A-Z]/, ' \0')   
> +- if @dmtfColItems 
> +  %label        
> +    = newName.capitalize.pluralize + ":"  
> +  %table{ :style => "width:52%;"}
> +    - @dmtfColItems.map do |template|
> +      - puts template.inspect
> +      %tr
> +        %td
> +          %a{ :href => template["href"] }= template["name"]
> +%br          
> +%a{ :href => HOST_API_PATH + "/" + @dmtfitem["uri"] + "/new"}= "New " + newName.downcase  
> \ No newline at end of file
> diff --git a/server/views/cimi/collection/response.xml.haml b/server/views/cimi/collection/response.xml.haml
> new file mode 100644
> index 0000000..ef931fe
> --- /dev/null
> +++ b/server/views/cimi/collection/response.xml.haml
> @@ -0,0 +1,3 @@
> +!!!XML
> +%ReturnCode{ :xmlns => CMWG_NAMESPACE }
> +  %Status= "Success"
> diff --git a/server/views/cimi/error.html.haml b/server/views/cimi/error.html.haml
> new file mode 100644
> index 0000000..155180d
> --- /dev/null
> +++ b/server/views/cimi/error.html.haml
> @@ -0,0 +1,31 @@
> +!!!
> +!!! XML
> +
> +%html
> +  %head
> +    = stylesheet_link_tag '/stylesheets/compiled/screen.css', :media => 'screen, projection'
> +    = stylesheet_link_tag '/stylesheets/compiled/print.css', :media => 'print'
> +    /[if lt IE 8]
> +      = stylesheet_link_tag '/stylesheets/compiled/ie.css', :media => 'screen, projection'
> +    = stylesheet_link_tag '/stylesheets/compiled/application.css', :media => 'screen, projection'
> +    %script{:type => "text/javascript", :src => "/javascripts/jquery-1.4.2.min.js" }
> +    %script{:type => "text/javascript", :src => "/javascripts/application.js" }
> +  %body
> +    #wrapper
> +      #header
> +        = link_to image_tag( "/images/logo-wide.png" ), root_url
> +      = bread_crumb
> +      #content{:class => :error}
> +        = yield
> +      #footer
> +        #formats
> +          Format:
> +          =link_to_format(:xml)
> +          |
> +          =link_to_format(:json)
> +        #driver_info
> +          Driver: #{driver_symbol} | API version: #{settings.version}
> +        #copyright
> +          Copyright 2009-2011
> +          %a{:href => 'http://incubator.apache.org/deltacloud/'} The Apache Software Foundation
> +          and individual contributors.
> diff --git a/server/views/cimi/errors/400.html.haml b/server/views/cimi/errors/400.html.haml
> new file mode 100644
> index 0000000..1a135f9
> --- /dev/null
> +++ b/server/views/cimi/errors/400.html.haml
> @@ -0,0 +1,41 @@
> +%div{ :'data-role' => :content, :'data-theme' => 'b'}
> +  %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +    %li{ :'data-role' => 'list-divider'} Server message
> +    %li
> +      %h3=[@error.class.name, @error.message].join(' - ')
> +    %li{ :'data-role' => 'list-divider'} Original request URI
> +    %li
> +      %a{ :href => request.env['REQUEST_URI'], :'data-ajax' => 'false'}
> +        %span=request.env['REQUEST_URI']
> +        %span{ :class => 'ui-li-count'} Retry
> +    %li{ :'data-role' => 'list-divider'} Error details
> +    %li
> +      - if @error.class.method_defined? :details
> +        %p= @error.details
> +      - else
> +        %em No details
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Backtrace
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      %li
> +        %pre=@error.backtrace.join("\n")
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Parameters
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - if params.keys.empty?
> +        %li{ :'data-role' => 'list-divider'} No parameters
> +      - params.each do |key, value|
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> +
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Request details
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - request.env.each do |key, value|
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> diff --git a/server/views/cimi/errors/400.xml.haml b/server/views/cimi/errors/400.xml.haml
> new file mode 100644
> index 0000000..4f2723f
> --- /dev/null
> +++ b/server/views/cimi/errors/400.xml.haml
> @@ -0,0 +1,4 @@
> +%error{:url => "#{request.env['REQUEST_URI']}", :status => "#{response.status}"}
> +  %parameter #{@error.name}
> +  %message< #{cdata @error.message}
> +
> diff --git a/server/views/cimi/errors/401.html.haml b/server/views/cimi/errors/401.html.haml
> new file mode 100644
> index 0000000..1a135f9
> --- /dev/null
> +++ b/server/views/cimi/errors/401.html.haml
> @@ -0,0 +1,41 @@
> +%div{ :'data-role' => :content, :'data-theme' => 'b'}
> +  %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +    %li{ :'data-role' => 'list-divider'} Server message
> +    %li
> +      %h3=[@error.class.name, @error.message].join(' - ')
> +    %li{ :'data-role' => 'list-divider'} Original request URI
> +    %li
> +      %a{ :href => request.env['REQUEST_URI'], :'data-ajax' => 'false'}
> +        %span=request.env['REQUEST_URI']
> +        %span{ :class => 'ui-li-count'} Retry
> +    %li{ :'data-role' => 'list-divider'} Error details
> +    %li
> +      - if @error.class.method_defined? :details
> +        %p= @error.details
> +      - else
> +        %em No details
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Backtrace
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      %li
> +        %pre=@error.backtrace.join("\n")
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Parameters
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - if params.keys.empty?
> +        %li{ :'data-role' => 'list-divider'} No parameters
> +      - params.each do |key, value|
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> +
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Request details
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - request.env.each do |key, value|
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> diff --git a/server/views/cimi/errors/401.xml.haml b/server/views/cimi/errors/401.xml.haml
> new file mode 100644
> index 0000000..bfa9111
> --- /dev/null
> +++ b/server/views/cimi/errors/401.xml.haml
> @@ -0,0 +1,3 @@
> +%error{:url => "#{request.env['REQUEST_URI']}", :status => "#{response.status}"}
> +  %message< #{cdata @error.message}
> +
> diff --git a/server/views/cimi/errors/403.html.haml b/server/views/cimi/errors/403.html.haml
> new file mode 100644
> index 0000000..781b6ae
> --- /dev/null
> +++ b/server/views/cimi/errors/403.html.haml
> @@ -0,0 +1,42 @@
> +%div{ :'data-role' => :content, :'data-theme' => 'b'}
> +  %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +    %li{ :'data-role' => 'list-divider'} Server message
> +    %li
> +      %h3=[@error.class.name, @error.message].join(' - ')
> +    %li{ :'data-role' => 'list-divider'} Original request URI
> +    %li
> +      %a{ :href => request.env['REQUEST_URI'], :'data-ajax' => 'false'}
> +        %span=request.env['REQUEST_URI']
> +        %span{ :class => 'ui-li-count'} Retry
> +    %li{ :'data-role' => 'list-divider'} Error details
> +    %li
> +      - if @error.class.method_defined? :details
> +        %p= @error.details
> +      - else
> +        %em No details
> +
> +  - if @error.backtrace
> +    %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +      %h3 Backtrace
> +      %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +        %li
> +          %pre=@error.backtrace.join("\n")
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Parameters
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - if params.keys.empty?
> +        %li{ :'data-role' => 'list-divider'} No parameters
> +      - params.each do |key, value|
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> +
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Request details
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - request.env.each do |key, value|
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> diff --git a/server/views/cimi/errors/403.xml.haml b/server/views/cimi/errors/403.xml.haml
> new file mode 100644
> index 0000000..3bad335
> --- /dev/null
> +++ b/server/views/cimi/errors/403.xml.haml
> @@ -0,0 +1,2 @@
> +%error{:url => "#{request.env['REQUEST_URI']}", :status => "#{response.status}"}
> +  %message Method not allowed for this resource
> diff --git a/server/views/cimi/errors/404.html.haml b/server/views/cimi/errors/404.html.haml
> new file mode 100644
> index 0000000..a9bbe34
> --- /dev/null
> +++ b/server/views/cimi/errors/404.html.haml
> @@ -0,0 +1,29 @@
> +%div{ :'data-role' => :content, :'data-theme' => 'b'}
> +  %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +    %li{ :'data-role' => 'list-divider'} Server message
> +    %li
> +      %h3 Not Found
> +    %li{ :'data-role' => 'list-divider'} Original request URI
> +    %li
> +      %a{ :href => request.env['REQUEST_URI'], :'data-ajax' => 'false'}
> +        %span=request.env['REQUEST_URI']
> +        %span{ :class => 'ui-li-count'} Retry
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Parameters
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - if params.keys.empty?
> +        %li{ :'data-role' => 'list-divider'} No parameters
> +      - params.each do |key, value|
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> +
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Request details
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - request.env.each do |key, value|
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> diff --git a/server/views/cimi/errors/404.xml.haml b/server/views/cimi/errors/404.xml.haml
> new file mode 100644
> index 0000000..47aede6
> --- /dev/null
> +++ b/server/views/cimi/errors/404.xml.haml
> @@ -0,0 +1,2 @@
> +%error{:url => "#{request.env['REQUEST_URI']}", :status => "#{response.status}"}
> +  %message Resource not found
> diff --git a/server/views/cimi/errors/405.html.haml b/server/views/cimi/errors/405.html.haml
> new file mode 100644
> index 0000000..12e51b0
> --- /dev/null
> +++ b/server/views/cimi/errors/405.html.haml
> @@ -0,0 +1,29 @@
> +%div{ :'data-role' => :content, :'data-theme' => 'b'}
> +  %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +    %li{ :'data-role' => 'list-divider'} Server message
> +    %li
> +      %h3 Method not allowed on given resource
> +    %li{ :'data-role' => 'list-divider'} Original request URI
> +    %li
> +      %a{ :href => request.env['REQUEST_URI'], :'data-ajax' => 'false'}
> +        %span=request.env['REQUEST_URI']
> +        %span{ :class => 'ui-li-count'} Retry
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Parameters
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - if params.keys.empty?
> +        %li{ :'data-role' => 'list-divider'} No parameters
> +      - params.each do |key, value|
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> +
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Request details
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - request.env.each do |key, value|
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> diff --git a/server/views/cimi/errors/405.xml.haml b/server/views/cimi/errors/405.xml.haml
> new file mode 100644
> index 0000000..e0198f5
> --- /dev/null
> +++ b/server/views/cimi/errors/405.xml.haml
> @@ -0,0 +1,5 @@
> +%error{:url => "#{request.env['REQUEST_URI']}", :status => "#{response.status}"}
> +  %message
> +    Requested method not allowed
> +  %method
> +    =request.env['REQUEST_METHOD']
> diff --git a/server/views/cimi/errors/500.html.haml b/server/views/cimi/errors/500.html.haml
> new file mode 100644
> index 0000000..19cf090
> --- /dev/null
> +++ b/server/views/cimi/errors/500.html.haml
> @@ -0,0 +1,43 @@
> +%div{ :'data-role' => :content, :'data-theme' => 'b'}
> +  %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +    %li{ :'data-role' => 'list-divider'} Server message
> +    %li
> +      %h3=[@error.class.name, @error.message].join(' - ')
> +    %li{ :'data-role' => 'list-divider'} Original request URI
> +    %li
> +      %a{ :href => request.env['REQUEST_URI'], :'data-ajax' => 'false'}
> +        %span=request.env['REQUEST_URI']
> +        %span{ :class => 'ui-li-count'} Retry
> +    %li{ :'data-role' => 'list-divider'} Error details
> +    %li
> +      - if @error.class.method_defined? :details
> +        %p= @error.details
> +      - else
> +        %em No details
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Backtrace
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      %li
> +        %pre=@error.backtrace.join("\n")
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Parameters
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - if params.keys.empty?
> +        %li{ :'data-role' => 'list-divider'} No parameters
> +      - params.each do |key, value|
> +        - next if value.inspect.to_s == '#'
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> +
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Request details
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - request.env.each do |key, value|
> +        - next if value.inspect.to_s == '#'
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> diff --git a/server/views/cimi/errors/500.xml.haml b/server/views/cimi/errors/500.xml.haml
> new file mode 100644
> index 0000000..69c242e
> --- /dev/null
> +++ b/server/views/cimi/errors/500.xml.haml
> @@ -0,0 +1,5 @@
> +%error{:url => "#{request.env['REQUEST_URI']}", :status => "#{response.status}"}
> +  %kind backend_error
> +  %backend{ :driver => driver_symbol }
> +    %code=response.status
> +  %message< #{cdata @error.message}
> diff --git a/server/views/cimi/errors/502.html.haml b/server/views/cimi/errors/502.html.haml
> new file mode 100644
> index 0000000..19cf090
> --- /dev/null
> +++ b/server/views/cimi/errors/502.html.haml
> @@ -0,0 +1,43 @@
> +%div{ :'data-role' => :content, :'data-theme' => 'b'}
> +  %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +    %li{ :'data-role' => 'list-divider'} Server message
> +    %li
> +      %h3=[@error.class.name, @error.message].join(' - ')
> +    %li{ :'data-role' => 'list-divider'} Original request URI
> +    %li
> +      %a{ :href => request.env['REQUEST_URI'], :'data-ajax' => 'false'}
> +        %span=request.env['REQUEST_URI']
> +        %span{ :class => 'ui-li-count'} Retry
> +    %li{ :'data-role' => 'list-divider'} Error details
> +    %li
> +      - if @error.class.method_defined? :details
> +        %p= @error.details
> +      - else
> +        %em No details
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Backtrace
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      %li
> +        %pre=@error.backtrace.join("\n")
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Parameters
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - if params.keys.empty?
> +        %li{ :'data-role' => 'list-divider'} No parameters
> +      - params.each do |key, value|
> +        - next if value.inspect.to_s == '#'
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> +
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Request details
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - request.env.each do |key, value|
> +        - next if value.inspect.to_s == '#'
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> diff --git a/server/views/cimi/errors/502.xml.haml b/server/views/cimi/errors/502.xml.haml
> new file mode 100644
> index 0000000..6e7a7b8
> --- /dev/null
> +++ b/server/views/cimi/errors/502.xml.haml
> @@ -0,0 +1,7 @@
> +%error{:url => "#{request.env['REQUEST_URI']}", :status => "#{response.status}"}
> +  %kind backend_error
> +  %backend{ :driver => driver_symbol }
> +    %code= @error.code
> +    - if @error.respond_to?(:details) && @error.details
> +      %details< #{cdata @error.details.join("\n")}
> +  %message< #{cdata @error.message}
> diff --git a/server/views/cimi/errors/backend_capability_failure.html.haml b/server/views/cimi/errors/backend_capability_failure.html.haml
> new file mode 100644
> index 0000000..3659ac5
> --- /dev/null
> +++ b/server/views/cimi/errors/backend_capability_failure.html.haml
> @@ -0,0 +1,29 @@
> +%div{ :'data-role' => :content, :'data-theme' => 'b'}
> +  %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +    %li{ :'data-role' => 'list-divider'} Server message
> +    %li
> +      %h3 Backend capability failure
> +    %li{ :'data-role' => 'list-divider'} Original request URI
> +    %li
> +      %a{ :href => request.env['REQUEST_URI'], :'data-ajax' => 'false'}
> +        %span=request.env['REQUEST_URI']
> +        %span{ :class => 'ui-li-count'} Retry
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Parameters
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - if params.keys.empty?
> +        %li{ :'data-role' => 'list-divider'} No parameters
> +      - params.each do |key, value|
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> +
> +
> +  %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +    %h3 Request details
> +    %ul{ :'data-role' => :listview , :'data-inset' => :true, :'data-divider-theme' => 'e'}
> +      - request.env.each do |key, value|
> +        %li{ :'data-role' => 'list-divider'}=key
> +        %li
> +          %span{:style => 'font-weight:normal;'}=value.inspect
> diff --git a/server/views/cimi/layout.html.haml b/server/views/cimi/layout.html.haml
> new file mode 100644
> index 0000000..0b89aaa
> --- /dev/null
> +++ b/server/views/cimi/layout.html.haml
> @@ -0,0 +1,32 @@
> +!!!
> +!!! XML
> +
> +%html
> +  %head
> +    = stylesheet_link_tag '/stylesheets/compiled/screen.css', :media => 'screen, projection'
> +    = stylesheet_link_tag '/stylesheets/compiled/print.css', :media => 'print'
> +    /[if lt IE 8]
> +      = stylesheet_link_tag '/stylesheets/compiled/ie.css', :media => 'screen, projection'
> +    = stylesheet_link_tag '/stylesheets/compiled/application.css', :media => 'screen, projection'
> +    %script{:type => "text/javascript", :src => "/javascripts/jquery-1.4.2.min.js" }
> +    %script{:type => "text/javascript", :src => "/javascripts/application.js" }
> +    %script{:type => "text/javascript", :src => "/javascripts/cmwgapp.js" }
> +  %body
> +    #wrapper
> +      #header
> +        = link_to image_tag( "/images/logo-wide.png" ), root_url
> +      = bread_crumb_ext
> +      #content
> +        = yield
> +      #footer
> +        #formats
> +          Format:
> +          =link_to_format(:xml)
> +          |
> +          =link_to_format(:json)
> +        #driver_info
> +          Driver: #{driver_symbol} | API version: #{settings.version}
> +        #copyright
> +          Copyright 2009-2011
> +          %a{:href => 'http://incubator.apache.org/deltacloud/'} The Apache Software Foundation
> +          and individual contributors.
> diff --git a/server/views/cimi/machine/index.html.haml b/server/views/cimi/machine/index.html.haml
> new file mode 100644
> index 0000000..da883f3
> --- /dev/null
> +++ b/server/views/cimi/machine/index.html.haml
> @@ -0,0 +1,35 @@
> +%h1 Machines
> +
> +%table.display
> +  %thead
> +    %tr
> +      %th ID
> +      %th Owner
> +      %th Name
> +      %th Machine Image
> +      %th Machine Configuration
> +      %th State
> +      %th Actions
> +  %tbody
> +    - @machines.each do |machine|
> +      %tr
> +        %td
> +          = link_to truncate_words(machine.id), machine_url + "/" + machine.id
> +        %td
> +          = link_to machine.owner_id, "#{machine_url}?owner_id=#{machine.owner_id}"
> +        %td
> +          = machine.name
> +        %td
> +          = link_to machine.image_id, HOST_API_PATH + "/machineImage/" + machine.image_id
> +        %td
> +          = link_to machine.instance_profile.id, HOST_API_PATH + "/machineConfiguration/" + machine.instance_profile.id
> +        %td
> +          = machine.state.to_s.capitalize
> +        %td
> +          -machine.actions.each do |action|
> +            - if action.to_s == "destroy"
> +              = link_to_action_ext action.to_s.capitalize, HOST_API_PATH + "/machine/" + machine.id, "DELETE", {:refresh => "true"}
> +            - else
> +              = link_to_action_ext action.to_s.capitalize, HOST_API_PATH + "/machine/" + machine.id, "PUT", {:action => action.to_s, :refresh => "true" }
> +          
> +          
> diff --git a/server/views/cimi/machine/index.json.haml b/server/views/cimi/machine/index.json.haml
> new file mode 100644
> index 0000000..caccd48
> --- /dev/null
> +++ b/server/views/cimi/machine/index.json.haml
> @@ -0,0 +1,6 @@
> +!!! XML
> +%Machines{:xmlns => "http://www.dmtf.org/cmp", :"xmlns:atom" => "http://atom.org"}
> +  %uri=machine_url
> +  %timestamp= Time.new.to_i.to_s
> +  - @machines.each do |machine|
> +    %atom:link{ :rel => "machine", :href => machine_url + "/" + machine.image_id }
> diff --git a/server/views/cimi/machine/index.xml.haml b/server/views/cimi/machine/index.xml.haml
> new file mode 100644
> index 0000000..08263f7
> --- /dev/null
> +++ b/server/views/cimi/machine/index.xml.haml
> @@ -0,0 +1,6 @@
> +!!! XML
> +%Machines{:xmlns => "http://www.dmtf.org/cimi", :"xmlns:atom" => "http://atom.org"}
> +  %uri=machine_url
> +  %timestamp= Time.new.to_i.to_s
> +  - @machines.each do |machine|
> +    %atom:link{ :rel => "machine", :href => machine_url + "/" + machine.image_id }
> diff --git a/server/views/cimi/machine/instanceToImage.html.haml b/server/views/cimi/machine/instanceToImage.html.haml
> new file mode 100644
> index 0000000..6feab80
> --- /dev/null
> +++ b/server/views/cimi/machine/instanceToImage.html.haml
> @@ -0,0 +1,32 @@
> +%h1 Create machine image by using a machine
> +
> +%form{ :action => HOST_API_PATH + "/machineImage" }
> +  %p
> +    %label
> +      Instance ID:
> +  %p
> +    = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
> +    %input{ :name => "instance_id_display", :size => 30, :value => @instance.id, :disabled => true }
> +    %input{ :name => :instance_id, :type => :hidden, :value => @instance.id }/
> +    =  "<br /><br/>"
> +  %p
> +  %p
> +    %label
> +      Machine Image Name:
> +  %p
> +    = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
> +    %input{ :name => "name", :size => 30, :value => "sample name"}
> +    =  "<br /><br/>"
> +  %p
> +  %p
> +    %label
> +      Machine Image Description:
> +  %p
> +    = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
> +    %textarea{ :name => :description, :cols => 50, :rows => 10}
> +    =  "<br /><br/>"
> +  %p
> +  %p
> +    = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"
> +    %input{ :type => :button, :name => "commit", :value => "Create machine image", :onClick => "return doPost(this)" }/
> +    %input{ :name => "refresh", :value => false, :type => :hidden}
> diff --git a/server/views/cimi/machine/new.html.haml b/server/views/cimi/machine/new.html.haml
> new file mode 100644
> index 0000000..3b1b667
> --- /dev/null
> +++ b/server/views/cimi/machine/new.html.haml
> @@ -0,0 +1,87 @@
> +=header "Launch new instance"
> +=subheader @image.description
> +
> +%div{ :'data-role' => :content, :'data-theme' => 'c', :class => 'middle-dialog'}
> +  %form{ :action => instances_url, :method => :post, :class => :new_instance }
> +    %input{ :name => :image_id, :type => :hidden, :value => @instance.image_id }/
> +
> +    %div{ 'data-role' => :fieldcontain }
> +      %label{ :for => :name} Instance name:
> +      %input{ :type => :text, :id => :name, :name => :name, :value => '' }
> +
> +    %div{ 'data-role' => :collapsible, 'data-collapsed' => "true"}
> +      %h3 Additional parameters
> +
> +      - if driver_has_feature?(:user_data)
> +        %div{ 'data-role' => :fieldcontain }
> +          %label{ :for => :user_data} Base64 encoded user-data:
> +          %textarea{ :id => :user_data, :name => :user_data, :value => '' }
> +          %br/
> +          %a{ :href => "", :onclick => 'encodeb64();', :'data-ajax' => 'false'} Encode data
> +
> +      - if driver_has_feature?(:instance_count)
> +        %div{ 'data-role' => :fieldcontain }
> +          %label{ :for => :instance_count} # of instances to be launched:
> +          %input{ :type => :text, :id => :instance_count, :name => :instance_count, :value => '1' }
> +
> +      - if driver_has_feature?(:authentication_key)
> +        %div{ 'data-role' => :fieldcontain }
> +          %label{ :for => :keyname, :class => 'ui-input-text'} Instance SSH key:
> +          %select{:name => 'keyname', :'data-native-menu' => "true" }
> +            %option{ :value => ''} None
> +            - @keys.each do |key|
> +              %option{ :value => key.id } #{key.id}
> +
> +      - if driver_has_feature?(:register_to_load_balancer)
> +        %div{ 'data-role' => :fieldcontain }
> +          %label{ :for => :load_balancer_id, :class => 'ui-input-text'} Register to loadbalancer:
> +          %select{:name => 'load_balancer_id', :'data-native-menu' => "true" }
> +            %option{ :value => ''} None
> +            - @load_balancers.each do |load_balancer|
> +              %option{:value => load_balancer.id} #{load_balancer.id}
> +
> +      - if driver_has_feature?(:firewalls)
> +        %div{ 'data-role' => :fieldcontain }
> +          %fieldset{ :'data-role' => 'controlgroup'}
> +            %legend Register to firewall:
> +            - @firewalls.each_index do |i|
> +              - if @firewalls[i].name == 'default'
> +                %input{:type => :checkbox, :value => @firewalls[i].name, :name => "firewalls#{i}", :checked => :true, :id => "firewalls#{i}"}/
> +                %label{:for => "firewalls#{i}"} Default
> +              - else
> +                %input{:type => :checkbox, :value => @firewalls[i].name, :name => "firewalls#{i}", :id => "firewalls#{i}"}/
> +                %label{:for => "firewalls#{i}"}=@firewalls[i].name
> +
> +    - if !@hardware_profiles.empty?
> +      %div{ 'data-role' => :fieldcontain }
> +        %h3 Instance profile
> +        %fieldset{ :'data-role' => :fieldcontain}
> +          - @hardware_profiles.each do |profile|
> +            %input{ :type => :radio, :name => 'hwp_id', :value => profile.name, :id => profile.name, :'data-theme' => 'b'}/
> +            %label{ :for => profile.name}=profile.name
> +            - profile.properties.reject { |prop| prop.fixed? }.each do |prop|
> +              %div{ :'data-role' => :fieldcontain}
> +                %label{ :for => "#{prop.param}_#{profile.name}" }=prop.name
> +                %span.radio-group-details
> +                  - if prop.kind == :enum
> +                    %select{ :size => 1, :name => prop.param }
> +                      - for v in prop.values
> +                        %option= v
> +                    = prop.unit
> +                  - elsif prop.kind == :range
> +                    %input{ :type => :range, :value => prop.first, :min => prop.first, :max => prop.last, :name => prop.param}
> +                  - else
> +                    %input{ :name => prop.param, :size => 10, :value => "#{prop.default}" }
> +                    = prop.unit
> +
> +    - if !@realms.empty?
> +      %div{ 'data-role' => :fieldcontain }
> +        %h3 Where do you want it?
> +        %fieldset{ :'data-role' => :fieldcontain}
> +          %legend
> +          - @realms.each do |realm|
> +            %div{ :'data-role' => :fieldcontain}
> +              %label{ :for => realm.id }= "#{realm.name}, #{realm.limit}"
> +              %input{ :type => :radio, :name => 'realm_id', :value => realm.id, :id => realm.id, :'data-theme' => 'b' }/
> +
> +    %button{ :type => :submit} Create instance
> diff --git a/server/views/cimi/machine/operation.html.haml b/server/views/cimi/machine/operation.html.haml
> new file mode 100644
> index 0000000..9ec81cf
> --- /dev/null
> +++ b/server/views/cimi/machine/operation.html.haml
> @@ -0,0 +1 @@
> +%h1 Command #{@operationParam['machineOperation']} for machine #{@operationParam['machineId']} has been issued. 
> \ No newline at end of file
> diff --git a/server/views/cimi/machine/operation.json.haml b/server/views/cimi/machine/operation.json.haml
> new file mode 100644
> index 0000000..7f87e57
> --- /dev/null
> +++ b/server/views/cimi/machine/operation.json.haml
> @@ -0,0 +1,3 @@
> +!!! XML
> +%Machine{:xmlns => "http://www.dmtf.org/cmp", :"xmlns:atom" => "http://atom.org"}
> +  %atom:link{ :rel => "machine #{@operationParam['machineId']}", :href => HOST_API_PATH + "/machine/" + @operationParam['machineOperation'] }
> diff --git a/server/views/cimi/machine/operation.xml.haml b/server/views/cimi/machine/operation.xml.haml
> new file mode 100644
> index 0000000..a6ddb43
> --- /dev/null
> +++ b/server/views/cimi/machine/operation.xml.haml
> @@ -0,0 +1,3 @@
> +!!! XML
> +%Machine{:xmlns => "http://www.dmtf.org/cimi", :"xmlns:atom" => "http://atom.org"}
> +  %atom:link{ :rel => "machine #{@operationParam['machineId']}", :href => HOST_API_PATH + "/machine/" + @operationParam['machineOperation'] }
> diff --git a/server/views/cimi/machine/show.html.haml b/server/views/cimi/machine/show.html.haml
> new file mode 100644
> index 0000000..d8741d1
> --- /dev/null
> +++ b/server/views/cimi/machine/show.html.haml
> @@ -0,0 +1,59 @@
> +%h1
> +  = @instance.id
> +
> +%dl
> +  %di
> +    %dt Machine Image
> +    %dd
> +      = link_to @instance.image_id, HOST_API_PATH + "/machineImage/" + @instance.image_id
> +  %di
> +    %dt Owner
> +    %dd
> +      = @instance.owner_id
> +  %di
> +    %dt Name
> +    %dd
> +      = @instance.name
> +  %di
> +    %dt Machine Configuration
> +    %dd
> +      - prof = @instance.instance_profile
> +      = link_to prof.id, HOST_API_PATH + "/machineConfiguration/" + prof.id
> +  %di
> +    %dt System (Realm)
> +    %dd
> +      = @instance.realm_id ? link_to(@instance.realm_id, HOST_API_PATH + "/system/" + @instance.realm_id) : 'default'
> +  %di
> +    %dt State
> +    %dd
> +      = @instance.state.to_s.capitalize
> +  %di
> +    %dt Public Addresses
> +    %dd
> +      = @instance.public_addresses.collect { |address| "<div>#{address}</div>" }.join
> +  %di
> +    %dt Private Addresses
> +    %dd
> +      = @instance.private_addresses.collect { |address| "<div>#{address}</div>" }.join
> +  - if @instance.password
> +    %di
> +      %dt Username
> +      %dd
> +        = @instance.username
> +    %di
> +      %dt Password
> +      %dd
> +        = @instance.password
> +  %di
> +    %dt
> +    %dd
> +      -@instance.actions.each do |action|
> +        - if action.to_s == "destroy"
> +          = link_to_action_ext action.to_s.capitalize, HOST_API_PATH + "/machine/" + @instance.id, "DELETE", { :refresh => "false" }
> +        - else
> +          = link_to_action_ext action.to_s.capitalize, HOST_API_PATH + "/machine/" + @instance.id, "PUT", {:action => action.to_s, :refresh => "true" }
> +    %dt
> +    %dd
> +      - if @instance.can_create_image?
> +        = link_to "Create new Machine Image by using this machine", HOST_API_PATH + "/machine/#{@instance.id}/createView"
> +
> diff --git a/server/views/cimi/machine/show.json.haml b/server/views/cimi/machine/show.json.haml
> new file mode 100644
> index 0000000..d41a4c7
> --- /dev/null
> +++ b/server/views/cimi/machine/show.json.haml
> @@ -0,0 +1,24 @@
> +!!! XML
> +%Machine{:xmlns => "http://www.dmtf.org/cimi", :"xmlns:atom" => "http://atom.org"}
> +  %uri= machine_url + "/" + @instance.id
> +  %timestamp= Time.new.to_i.to_s
> +  %id= @instance.id
> +  %owner= @instance.owner_id
> +  %name= @instance.name
> +  %state= @instance.state.to_s.capitalize
> +  %publicAddresses= @instance.public_addresses.collect { |address| "#{address} " }.join
> +  %privateAddresses= @instance.private_addresses.collect { |address| "#{address} " }.join
> +  - if @instance.password
> +    %username= @instance.username
> +    %password= @instance.password
> +  %atom:link{ :rel => "machineImage", :href => HOST_API_PATH + "/machineImage/" + @instance.image_id }
> +  %atom:link{ :rel => "machineConfiguration", :href => HOST_API_PATH + "/machineConfiguration/" + @instance.instance_profile.id }
> +  %atom:link{ :rel => "system", :href => @instance.realm_id ? (HOST_API_PATH + "/system/" + @instance.realm_id) : 'default' }
> +  -@instance.actions.each do |action|
> +    - if action.to_s == "destroy"
> +      %atom:link{ :rel => action.to_s, :href => HOST_API_PATH + "/machine/" + @instance.id, :method => "DELETE" }
> +    - else
> +      %atom:link{ :rel => action.to_s, :href => HOST_API_PATH + "/machine/" + @instance.id, :method =>"PUT" }
> +  - if @instance.can_create_image?
> +    %atom:link{ :rel => "createMachineImageFromMachine", :href => HOST_API_PATH + "/machine", :method => "POST", :instance_id => @instance.id }
> +
> diff --git a/server/views/cimi/machine/show.xml.haml b/server/views/cimi/machine/show.xml.haml
> new file mode 100644
> index 0000000..d41a4c7
> --- /dev/null
> +++ b/server/views/cimi/machine/show.xml.haml
> @@ -0,0 +1,24 @@
> +!!! XML
> +%Machine{:xmlns => "http://www.dmtf.org/cimi", :"xmlns:atom" => "http://atom.org"}
> +  %uri= machine_url + "/" + @instance.id
> +  %timestamp= Time.new.to_i.to_s
> +  %id= @instance.id
> +  %owner= @instance.owner_id
> +  %name= @instance.name
> +  %state= @instance.state.to_s.capitalize
> +  %publicAddresses= @instance.public_addresses.collect { |address| "#{address} " }.join
> +  %privateAddresses= @instance.private_addresses.collect { |address| "#{address} " }.join
> +  - if @instance.password
> +    %username= @instance.username
> +    %password= @instance.password
> +  %atom:link{ :rel => "machineImage", :href => HOST_API_PATH + "/machineImage/" + @instance.image_id }
> +  %atom:link{ :rel => "machineConfiguration", :href => HOST_API_PATH + "/machineConfiguration/" + @instance.instance_profile.id }
> +  %atom:link{ :rel => "system", :href => @instance.realm_id ? (HOST_API_PATH + "/system/" + @instance.realm_id) : 'default' }
> +  -@instance.actions.each do |action|
> +    - if action.to_s == "destroy"
> +      %atom:link{ :rel => action.to_s, :href => HOST_API_PATH + "/machine/" + @instance.id, :method => "DELETE" }
> +    - else
> +      %atom:link{ :rel => action.to_s, :href => HOST_API_PATH + "/machine/" + @instance.id, :method =>"PUT" }
> +  - if @instance.can_create_image?
> +    %atom:link{ :rel => "createMachineImageFromMachine", :href => HOST_API_PATH + "/machine", :method => "POST", :instance_id => @instance.id }
> +
> diff --git a/server/views/cimi/machineAdmin/new.html.haml b/server/views/cimi/machineAdmin/new.html.haml
> new file mode 100644
> index 0000000..e3874ec
> --- /dev/null
> +++ b/server/views/cimi/machineAdmin/new.html.haml
> @@ -0,0 +1,47 @@
> +%h1 Create new machine admin
> +
> +%form{ :action => HOST_API_PATH + "/machineAdmin" }
> +  %input{ :name => :id, :type => :hidden, :value => @dmtfitem["uri"] }/
> +  %input{ :name => :xmlRootNode, :type => :hidden, :value => @xmlRootNode }/
> +  %input{ :name => :refreshURI, :type => :hidden, :value => HOST_API_PATH + "/collection/machineAdmin" }/
> +  %p
> +    %label
> +      Name:
> +  %p
> +    %input{ :name => :name, :size => 50, :value => @dmtfitem["name"], :style => "width:50%;" }
> +    %input{ :name => :created, :type => :hidden, :size => 50, :value => @dmtfitem["created"] }
> +  %p
> +  %br
> +    %label
> +      Description:
> +  %p
> +    %textarea{ :name => :description, :cols => 50, :rows => 4, :style => "width:50%;" } #{@dmtfitem['description']}       
> +  %p
> +  %br
> +    %label
> +      Properties:      
> +  %p
> +    %table{ :style => "width:50%;", :id => "propertyTable"}
> +      - if @dmtfitem["property"]
> +        - if @dmtfitem["property"]["name"] && @dmtfitem["property"]["content"] 
> +          - newPropertyObj = {"#{@dmtfitem['property']['name']}" => {"content" => @dmtfitem["property"]["content"]}}
> +        - else
> +          - newPropertyObj = @dmtfitem["property"]
> +          
> +        - iter = -1
> +        - newPropertyObj.each_pair do |key, value| 
> +          - iter += 1       
> +          %tr
> +            %td
> +              %input{ :name => "param_name_" + iter.to_s, :size => 30, :value => key }                
> +            %td
> +              %input{ :name => "param_value_" + iter.to_s, :size => 30, :value => value["content"] }
> +            %td
> +              %input{ :type => :button, :value => "Remove", :onClick => "return removeProperty(this)" }
> +
> +    %input{ :type => :button, :name => "commit", :value => "Add new property", :onClick => "return AddNewPproperty('propertyTable')" }
> +  %p
> +  %br         
> +  %input{ :type => :button, :name => "commit", :value => "Submit", :onClick => "return doXmlPost(this)" }/
> +  %input{ :name => "refresh", :value => false, :type => :hidden}
> +              
> diff --git a/server/views/cimi/machineAdmin/show.html.haml b/server/views/cimi/machineAdmin/show.html.haml
> new file mode 100644
> index 0000000..ce55366
> --- /dev/null
> +++ b/server/views/cimi/machineAdmin/show.html.haml
> @@ -0,0 +1,47 @@
> +%h1 Machine Admin
> +
> +%form{ :action => HOST_API_PATH + "/machineAdmin" }
> +  %input{ :name => :id, :type => :hidden, :value => @dmtfitem["uri"] }/
> +  %input{ :name => :xmlRootNode, :type => :hidden, :value => @xmlRootNode }/
> +  %input{ :name => :refreshURI, :type => :hidden, :value => HOST_API_PATH + "/collection/machineAdmin" }/  
> +  %p
> +    %label
> +      Name:
> +  %p
> +    %input{ :name => :name, :size => 50, :value => @dmtfitem["name"], :style => "width:50%;" }
> +    %input{ :name => :created, :type => :hidden, :size => 50, :value => @dmtfitem["created"] }
> +  %p
> +  %br
> +    %label
> +      Description:
> +  %p
> +    %textarea{ :name => :description, :cols => 50, :rows => 4, :style => "width:50%;" } #{@dmtfitem['description']}       
> +  %p
> +  %br
> +    %label
> +      Properties:      
> +  %p
> +    %table{ :style => "width:50%;", :id => "propertyTable"}
> +      - if @dmtfitem["property"]
> +        - if @dmtfitem["property"]["name"] && @dmtfitem["property"]["content"] 
> +          - newPropertyObj = {"#{@dmtfitem['property']['name']}" => {"content" => @dmtfitem["property"]["content"]}}
> +        - else
> +          - newPropertyObj = @dmtfitem["property"]
> +          
> +        - iter = -1
> +        - newPropertyObj.each_pair do |key, value|  
> +          - iter += 1      
> +          %tr
> +            %td
> +              %input{ :name => "param_name_" + iter.to_s, :size => 30, :value => key }                
> +            %td
> +              %input{ :name => "param_value_" + iter.to_s, :size => 30, :value => value["content"] }
> +            %td
> +              %input{ :type => :button, :value => "Remove", :onClick => "return removeProperty(this)" }
> +    %input{ :type => :button, :name => "commit", :value => "Add new property", :onClick => "return AddNewPproperty('propertyTable')" }
> +  %p
> +  %br         
> +  %input{ :type => :button, :name => "commit", :value => "Submit", :onClick => "return doXmlPut(this, true)" }/
> +  %input{ :type => :button, :name => "commit", :value => "Delete", :onClick => "return doXmlDelete(this, true)" }/
> +  %input{ :name => "refresh", :value => false, :type => :hidden}
> +              
> diff --git a/server/views/cimi/machineConfiguration/new.html.haml b/server/views/cimi/machineConfiguration/new.html.haml
> new file mode 100644
> index 0000000..0e71101
> --- /dev/null
> +++ b/server/views/cimi/machineConfiguration/new.html.haml
> @@ -0,0 +1,161 @@
> +%h1 Create new machine configuration
> +
> +%form{ :action => HOST_API_PATH + "/machineConfiguration" }
> +  %input{ :name => :id, :type => :hidden, :value => @dmtfitem["uri"] }/
> +  %input{ :name => :xmlRootNode, :type => :hidden, :value => @xmlRootNode }/
> +  %input{ :name => :refreshURI, :type => :hidden, :value => HOST_API_PATH + "/collection/machineConfiguration" }/
> +  %p
> +    %label
> +      Name:
> +  %p
> +    %input{ :name => :name, :size => 50, :value => @dmtfitem["name"], :style => "width:50%;" }
> +    %input{ :name => :created, :type => :hidden, :size => 50, :value => @dmtfitem["created"] }
> +  %p
> +  %br
> +    %label
> +      Description:
> +  %p
> +    %textarea{ :name => :description, :cols => 50, :rows => 4, :style => "width:50%;" } #{@dmtfitem['description']}       
> +  %p
> +  %br
> +    %label
> +      Properties:      
> +  %p
> +    %table{ :style => "width:50%;", :id => "propertyTable"}
> +      - if @dmtfitem["property"]
> +        - if @dmtfitem["property"]["name"] && @dmtfitem["property"]["content"] 
> +          - newPropertyObj = {"#{@dmtfitem['property']['name']}" => {"content" => @dmtfitem["property"]["content"]}}
> +        - else
> +          - newPropertyObj = @dmtfitem["property"]
> +          
> +        - iter = -1
> +        - newPropertyObj.each_pair do |key, value| 
> +          - iter += 1       
> +          %tr
> +            %td
> +              %input{ :name => "param_name_" + iter.to_s, :size => 30, :value => key }                
> +            %td
> +              %input{ :name => "param_value_" + iter.to_s, :size => 30, :value => value["content"] }
> +            %td
> +              %input{ :type => :button, :value => "Remove", :onClick => "return removeProperty(this)" }
> +    %input{ :type => :button, :name => "commit", :value => "Add new property", :onClick => "return AddNewPproperty('propertyTable')" }
> +  %p
> +  %br   
> +    %label
> +      Cpu:
> +  %p
> +    %input{ :name => :cpu, :size => 50, :value => @dmtfitem["cpu"], :style => "width:50%;" }
> +  %br
> +    %label
> +      Memory:
> +  %p
> +    %input{ :name => :memory_quantity, :size => 20, :value => @dmtfitem["memory"]["quantity"], :style => "width:10%;" } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> +    %input{ :name => :memory_units, :size => 20, :value => @dmtfitem["memory"]["units"], :style => "width:10%;" }
> +  %br
> +    %label
> +      Disk:
> +  %p
> +    %table{ :style => "width:50%;", :id => "diskTable"}
> +      - if @dmtfitem["disk"]
> +        - if @dmtfitem["disk"].kind_of?(Array) 
> +          - newPropertyObj = @dmtfitem["disk"]
> +        - else
> +          - newPropertyObj = [@dmtfitem["disk"]]
> +          
> +        - iter = -1
> +        %tr
> +          %td
> +            %label
> +              Quantity
> +          %td
> +            %label
> +              Units 
> +          %td
> +            %label
> +              GuestInterface
> +          %td &nbsp;
> +        - newPropertyObj.each do |disk| 
> +          - iter += 1       
> +          %tr
> +            %td
> +              %input{ :name => "disk_quantity_" + iter.to_s, :size => 10, :value => disk["capacity"]["quantity"] }                
> +            %td
> +              %input{ :name => "disk_units_" + iter.to_s, :size => 10, :value => disk["capacity"]["units"] }
> +            %td
> +              %input{ :name => "disk_guestInterface_" + iter.to_s, :size => 50, :value => disk["guestInterface"] }  
> +            %td
> +              %input{ :type => :button, :value => "Remove", :onClick => "return removeProperty(this)" }
> +    %input{ :type => :button, :name => "commit", :value => "Add new disk", :onClick => "return addDiskRow('diskTable')" }
> +      
> +  %br
> +          
> +  %input{ :type => :button, :name => "commit", :value => "Submit", :onClick => "return doXmlPost(this, fixupXml)" }/
> +  %input{ :name => "refresh", :value => false, :type => :hidden}
> +              
> +:javascript
> +  function fixupXml(theNode) {
> +    var xmlData = "<?xml version='1.0' encoding='utf-8' ?>";
> +    xmlData += "<" + $(theNode.form).attr("xmlRootNode").value + " xmlns='http://www.dmtf.org/cimi'>";
> +    xmlData += getStandardData(theNode);
> +    xmlData += "<cpu>" + $(theNode.form).attr("cpu").value + "</cpu>";
> +    xmlData += "<memory quantity='" + $(theNode.form).attr("memory_quantity").value + "' units='";
> +    xmlData += $(theNode.form).attr("memory_units").value + "' />"
> +    
> +    var index=0;
> +    subDisk = ""
> +    while ($(theNode.form).attr("disk_quantity_" + index)) {
> +      if ($(theNode.form).attr("disk_quantity_" + index).value != null &&
> +          $(theNode.form).attr("disk_quantity_" + index).value.length > 0) {
> +        subDisk += "<capacity quantity='" + $(theNode.form).attr("disk_quantity_" + index).value + "' units='" + 
> +                   $(theNode.form).attr("disk_units_" + index).value + "' />";
> +        subDisk += "<guestInterface>" + $(theNode.form).attr("disk_guestInterface_" + index).value + "</guestInterface>";
> +      }
> +      index++;
> +    } 
> +    if (subDisk.length > 0) {
> +      xmlData += "<disk>" + subDisk +  "</disk>";
> +    }
> +
> +    xmlData += "</" + $(theNode.form).attr("xmlRootNode").value + ">";
> +    
> +    return xmlData;
> +  } 
> +  
> +  function addDiskRow(tableId) {
> +    var tbl = document.getElementById(tableId);
> +    var lastRow = tbl.rows.length;
> +    // if there's no header row in the table, then iteration = lastRow + 1
> +    var iteration = lastRow - 1;
> +    var row = tbl.insertRow(lastRow);
> +    
> +    elNames = ['disk_quantity_', 'disk_units_', 'disk_guestInterface_'];
> +    elSizes = [10, 10, 50]
> +    elValues = ["200", "megabyte", ""]
> +    
> +    for (var index=0; index<elNames.length; index++) {
> +       var aCellTD = row.insertCell(index);
> +       var aCell = document.createElement('input');
> +       aCell.type = 'text';
> +       aCell.name = elNames[index] + iteration;
> +       aCell.id = aCell.name;
> +       aCell.size = elSizes[index];
> +       aCell.value = elValues[index];
> +       aCellTD.appendChild(aCell);
> +    }
> +    
> +    // select cell
> +    var cellRightBut = row.insertCell(elNames.length);
> +    var er = document.createElement('input');
> +    er.type = 'button';
> +    er.name = 'param_remove' + iteration;
> +    er.id = 'param_remove' + iteration;
> +    er.value = "Remove";
> +    er.tableRow = row
> +    $(er).click(function() {
> +     removeProperty(this); 
> +    })
> +  
> +    cellRightBut.appendChild(er);
> +  
> +  }
> +               
> diff --git a/server/views/cimi/machineConfiguration/show.html.haml b/server/views/cimi/machineConfiguration/show.html.haml
> new file mode 100644
> index 0000000..bfe48cb
> --- /dev/null
> +++ b/server/views/cimi/machineConfiguration/show.html.haml
> @@ -0,0 +1,160 @@
> +%h1 View/Edit machine configuration
> +
> +%form{ :action => HOST_API_PATH + "/machineConfiguration" }
> +  %input{ :name => :id, :type => :hidden, :value => @dmtfitem["uri"] }/
> +  %input{ :name => :xmlRootNode, :type => :hidden, :value => @xmlRootNode }/
> +  %input{ :name => :refreshURI, :type => :hidden, :value => HOST_API_PATH + "/collection/machineConfiguration" }/  
> +  %p
> +    %label
> +      Name:
> +  %p
> +    %input{ :name => :name, :size => 50, :value => @dmtfitem["name"], :style => "width:50%;" }
> +    %input{ :name => :created, :type => :hidden, :size => 50, :value => @dmtfitem["created"] }
> +  %p
> +  %br
> +    %label
> +      Description:
> +  %p
> +    %textarea{ :name => :description, :cols => 50, :rows => 4, :style => "width:50%;" } #{@dmtfitem['description']}       
> +  %p
> +  %br
> +    %label
> +      Properties:      
> +  %p
> +    %table{ :style => "width:50%;", :id => "propertyTable"}
> +      - if @dmtfitem["property"]
> +        - if @dmtfitem["property"]["name"] && @dmtfitem["property"]["content"] 
> +          - newPropertyObj = {"#{@dmtfitem['property']['name']}" => {"content" => @dmtfitem["property"]["content"]}}
> +        - else
> +          - newPropertyObj = @dmtfitem["property"]
> +          
> +        - iter = -1
> +        - newPropertyObj.each_pair do |key, value| 
> +          - iter += 1       
> +          %tr
> +            %td
> +              %input{ :name => "param_name_" + iter.to_s, :size => 30, :value => key }                
> +            %td
> +              %input{ :name => "param_value_" + iter.to_s, :size => 30, :value => value["content"] }
> +            %td
> +              %input{ :type => :button, :value => "Remove", :onClick => "return removeProperty(this)" }
> +    %input{ :type => :button, :name => "commit", :value => "Add new property", :onClick => "return AddNewPproperty('propertyTable')" }
> +  %p
> +  %br   
> +    %label
> +      Cpu:
> +  %p
> +    %input{ :name => :cpu, :size => 50, :value => @dmtfitem["cpu"], :style => "width:50%;" }
> +  %br
> +    %label
> +      Memory:
> +  %p
> +    %input{ :name => :memory_quantity, :size => 20, :value => @dmtfitem["memory"]["quantity"], :style => "width:10%;" } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> +    %input{ :name => :memory_units, :size => 20, :value => @dmtfitem["memory"]["units"], :style => "width:10%;" }
> +  %br
> +    %label
> +      Disk:
> +  %p
> +    %table{ :style => "width:50%;", :id => "diskTable"}
> +      - if @dmtfitem["disk"]
> +        - if @dmtfitem["disk"].kind_of?(Array) 
> +          - newPropertyObj = @dmtfitem["disk"]
> +        - else
> +          - newPropertyObj = [@dmtfitem["disk"]]
> +          
> +        - iter = -1
> +        %tr
> +          %td
> +            %label
> +              Quantity
> +          %td
> +            %label
> +              Units 
> +          %td
> +            %label
> +              GuestInterface
> +          %td &nbsp;
> +        - newPropertyObj.each do |disk| 
> +          - iter += 1       
> +          %tr
> +            %td
> +              %input{ :name => "disk_quantity_" + iter.to_s, :size => 10, :value => disk["capacity"]["quantity"] }                
> +            %td
> +              %input{ :name => "disk_units_" + iter.to_s, :size => 10, :value => disk["capacity"]["units"] }
> +            %td
> +              %input{ :name => "disk_guestInterface_" + iter.to_s, :size => 50, :value => disk["guestInterface"] }  
> +            %td
> +              %input{ :type => :button, :value => "Remove", :onClick => "return removeProperty(this)" }
> +    %input{ :type => :button, :name => "commit", :value => "Add new disk", :onClick => "return addDiskRow('diskTable')" }
> +      
> +  %br          
> +  %input{ :type => :button, :name => "commit", :value => "Submit", :onClick => "return doXmlPut(this, true, fixupXml)" }/
> +  %input{ :type => :button, :name => "commit", :value => "Delete", :onClick => "return doXmlDelete(this, true)" }/
> +              
> +:javascript
> +  function fixupXml(theNode) {
> +    var xmlData = "<?xml version='1.0' encoding='utf-8' ?>";
> +    xmlData += "<" + $(theNode.form).attr("xmlRootNode").value + " xmlns='http://www.dmtf.org/cimi'>";
> +    xmlData += getStandardData(theNode);
> +    xmlData += "<cpu>" + $(theNode.form).attr("cpu").value + "</cpu>";
> +    xmlData += "<memory quantity='" + $(theNode.form).attr("memory_quantity").value + "' units='";
> +    xmlData += $(theNode.form).attr("memory_units").value + "' />"
> +    
> +    var index=0;
> +    subDisk = ""
> +    while ($(theNode.form).attr("disk_quantity_" + index)) {
> +      if ($(theNode.form).attr("disk_quantity_" + index).value != null &&
> +          $(theNode.form).attr("disk_quantity_" + index).value.length > 0) {
> +        subDisk += "<capacity quantity='" + $(theNode.form).attr("disk_quantity_" + index).value + "' units='" + 
> +                   $(theNode.form).attr("disk_units_" + index).value + "' />";
> +        subDisk += "<guestInterface>" + $(theNode.form).attr("disk_guestInterface_" + index).value + "</guestInterface>";
> +      }
> +      index++;
> +    } 
> +    if (subDisk.length > 0) {
> +      xmlData += "<disk>" + subDisk +  "</disk>";
> +    }
> +
> +    xmlData += "</" + $(theNode.form).attr("xmlRootNode").value + ">";
> +    
> +    return xmlData;
> +  } 
> +  
> +  function addDiskRow(tableId) {
> +    var tbl = document.getElementById(tableId);
> +    var lastRow = tbl.rows.length;
> +    // if there's no header row in the table, then iteration = lastRow + 1
> +    var iteration = lastRow - 1;
> +    var row = tbl.insertRow(lastRow);
> +    
> +    elNames = ['disk_quantity_', 'disk_units_', 'disk_guestInterface_'];
> +    elSizes = [10, 10, 50]
> +    elValues = ["200", "megabyte", ""]
> +    
> +    for (var index=0; index<elNames.length; index++) {
> +       var aCellTD = row.insertCell(index);
> +       var aCell = document.createElement('input');
> +       aCell.type = 'text';
> +       aCell.name = elNames[index] + iteration;
> +       aCell.id = aCell.name;
> +       aCell.size = elSizes[index];
> +       aCell.value = elValues[index];
> +       aCellTD.appendChild(aCell);
> +    }
> +    
> +    // select cell
> +    var cellRightBut = row.insertCell(elNames.length);
> +    var er = document.createElement('input');
> +    er.type = 'button';
> +    er.name = 'param_remove' + iteration;
> +    er.id = 'param_remove' + iteration;
> +    er.value = "Remove";
> +    er.tableRow = row
> +    $(er).click(function() {
> +     removeProperty(this); 
> +    })
> +  
> +    cellRightBut.appendChild(er);
> +  
> +  }
> +               
> diff --git a/server/views/cimi/machineConfiguration/show.xml.haml b/server/views/cimi/machineConfiguration/show.xml.haml
> new file mode 100644
> index 0000000..285648b
> --- /dev/null
> +++ b/server/views/cimi/machineConfiguration/show.xml.haml
> @@ -0,0 +1,13 @@
> +- unless defined?(partial)
> +  !!! XML
> +%MachineConfiguration{ :xmlns => "http://www.dmtf.org/cimi", :"xmlns:atom" => "http://atom.org" }
> +  %uri=machineConfiguration_url + "/" + @profile.name
> +  %timestamp=Time.new.to_i.to_s
> +  %name=@profile.name
> +  %properties
> +    - @profile.each_property do |prop|
> +      - attr = { :name => prop.name, :kind => prop.kind, :unit => prop.unit }
> +      - if prop.kind == :fixed
> +        %property{ attr, :value => prop.value }/
> +      - else
> +        %property{ attr, :value => prop.default }
> diff --git a/server/views/cimi/machineImage/index.html.haml b/server/views/cimi/machineImage/index.html.haml
> new file mode 100644
> index 0000000..e5b8d3b
> --- /dev/null
> +++ b/server/views/cimi/machineImage/index.html.haml
> @@ -0,0 +1,25 @@
> +%h1 Machine Images
> +
> +%table.display
> +  %thead
> +    %tr
> +      %th
> +        ID
> +      %th
> +        Name
> +      %th
> +        Owner
> +      %th
> +        Description
> +  %tbody
> +    - @machineImages.each do |image|
> +      %tr
> +        %td
> +          = link_to image.id, machineImage_url+"/"+image.id
> +        %td
> +          = image.name
> +        %td
> +          = link_to image.owner_id, machineImage_url
> +        %td
> +          = image.description
> +
> diff --git a/server/views/cimi/machineImage/index.json.haml b/server/views/cimi/machineImage/index.json.haml
> new file mode 100644
> index 0000000..1c6033e
> --- /dev/null
> +++ b/server/views/cimi/machineImage/index.json.haml
> @@ -0,0 +1,6 @@
> +!!! XML
> +%MachineImages{:xmlns => "http://www.dmtf.org/cimi", :"xmlns:atom" => "http://atom.org"}
> +  %uri /api/machineImage
> +  %timestamp= Time.new.to_i.to_s
> +  - @elements.each do |image|
> +    %atom:link{ :rel => "MachineImage", :href => machineImage_url + "/" + image.id}
> diff --git a/server/views/cimi/machineImage/index.xml.haml b/server/views/cimi/machineImage/index.xml.haml
> new file mode 100644
> index 0000000..c678b5f
> --- /dev/null
> +++ b/server/views/cimi/machineImage/index.xml.haml
> @@ -0,0 +1,6 @@
> +!!! XML
> +%MachineImages{:xmlns => "http://www.dmtf.org/cimi", :"xmlns:atom" => "http://atom.org"}
> +  %uri /api/machineImage
> +  %timestamp= Time.new.to_i.to_s
> +  - @elements.each do |image|
> +    %atom:link{ :rel => "MachineImage", :href => machineImage_url + "/" + image.id}
> diff --git a/server/views/cimi/machineImage/show.html.haml b/server/views/cimi/machineImage/show.html.haml
> new file mode 100644
> index 0000000..87a5f62
> --- /dev/null
> +++ b/server/views/cimi/machineImage/show.html.haml
> @@ -0,0 +1,21 @@
> +%h1 machineImage
> +%h2
> +  = @machineImage.id
> +
> +%dl
> +  %di
> +    %dt Name
> +    %dd
> +      = @machineImage.id
> +    %dt Owner
> +    %dd
> +      = link_to @machineImage.owner_id, machineImage_url
> +    %dt Architecture
> +    %dd
> +      = @machineImage.architecture
> +    %dt Description
> +    %dd
> +      = @machineImage.description
> +    %dt
> +    %dd
> +      = link_to_action "Launch new machine", HOST_API_PATH + "/machine?image_id=#{@machineImage.id}", "#{@machineImage.id}"
> diff --git a/server/views/cimi/machineImage/show.json.haml b/server/views/cimi/machineImage/show.json.haml
> new file mode 100644
> index 0000000..b5f9817
> --- /dev/null
> +++ b/server/views/cimi/machineImage/show.json.haml
> @@ -0,0 +1,10 @@
> +- unless defined?(partial)
> +  !!! XML
> +%MachineImage{ :xmlns => "http://www.dmtf.org/cimi", :"xmlns:atom" => "http://atom.org" }
> +  %uri=machineImage_url + "/" + @machineImage.id
> +  %timestamp=Time.new.to_i.to_s
> +  %name=@machineImage.name
> +  %description=@machineImage.description
> +  %architecture=@machineImage.architecture
> +  %created
> +  %properties
> diff --git a/server/views/cimi/machineImage/show.xml.haml b/server/views/cimi/machineImage/show.xml.haml
> new file mode 100644
> index 0000000..43f710f
> --- /dev/null
> +++ b/server/views/cimi/machineImage/show.xml.haml
> @@ -0,0 +1,10 @@
> +- unless defined?(partial)
> +  !!! XML
> +%MachineImage{ :xmlns => "http://www.dmtf.org/cimi", :"xmlns:atom" => "http://atom.org" }
> +  %uri=machineImage_url + "/" + @machineImage.id
> +  %timestamp=Time.new.to_i.to_s
> +  %name=@machineImage.name
> +  %description=@machineImage.description
> +  %architecture=@machineImage.architecture
> +  %created
> +  %properties
> diff --git a/server/views/cimi/machineTemplate/new.html.haml b/server/views/cimi/machineTemplate/new.html.haml
> new file mode 100644
> index 0000000..52c2666
> --- /dev/null
> +++ b/server/views/cimi/machineTemplate/new.html.haml
> @@ -0,0 +1,79 @@
> +%h1 Create new machine template
> +
> +%form{ :action => HOST_API_PATH + "/machineTemplate" }
> +  %input{ :name => :id, :type => :hidden, :value => @dmtfitem["uri"] }/
> +  %input{ :name => :xmlRootNode, :type => :hidden, :value => @xmlRootNode }/
> +  %input{ :name => :refreshURI, :type => :hidden, :value => HOST_API_PATH + "/collection/machineTemplate" }/
> +  %p
> +    %label
> +      Name:
> +  %p
> +    %input{ :name => :name, :size => 50, :value => @dmtfitem["name"], :style => "width:50%;" }
> +    %input{ :name => :created, :type => :hidden, :size => 50, :value => @dmtfitem["created"] }
> +  %p
> +  %br
> +    %label
> +      Description:
> +  %p
> +    %textarea{ :name => :description, :cols => 50, :rows => 4, :style => "width:50%;" } #{@dmtfitem['description']}       
> +  %p
> +  %br
> +    %label
> +      Properties:      
> +  %p
> +    %table{ :style => "width:50%;", :id => "propertyTable"}
> +      - if @dmtfitem["property"]
> +        - if @dmtfitem["property"]["name"] && @dmtfitem["property"]["content"] 
> +          - newPropertyObj = {"#{@dmtfitem['property']['name']}" => {"content" => @dmtfitem["property"]["content"]}}
> +        - else
> +          - newPropertyObj = @dmtfitem["property"]
> +          
> +        - iter = -1
> +        - newPropertyObj.each_pair do |key, value| 
> +          - iter += 1       
> +          %tr
> +            %td
> +              %input{ :name => "param_name_" + iter.to_s, :size => 30, :value => key }                
> +            %td
> +              %input{ :name => "param_value_" + iter.to_s, :size => 30, :value => value["content"] }
> +            %td
> +              %input{ :type => :button, :value => "Remove", :onClick => "return removeProperty(this)" }
> +    %input{ :type => :button, :name => "commit", :value => "Add new property", :onClick => "return AddNewPproperty('propertyTable')" }
> +  %p
> +  %br
> +    %label
> +      TODO Need to handle machineConfiguration
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle machineImage
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle machineAdmins
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle volums
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle volumeTemplates
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle networkInterfaces
> +      
> +  %input{ :type => :button, :name => "commit", :value => "Submit", :onClick => "return doXmlPost(this, fixupXml)" }/
> +  %input{ :name => "refresh", :value => false, :type => :hidden}
> +              
> +:javascript
> +  function fixupXml(theNode) {
> +    var xmlData = "<?xml version='1.0' encoding='utf-8' ?>";
> +    xmlData += "<" + $(theNode.form).attr("xmlRootNode").value + " xmlns='http://www.dmtf.org/cimi'>";
> +    xmlData += getStandardData(theNode);
> +    xmlData += "</" + $(theNode.form).attr("xmlRootNode").value + ">";
> +    
> +    return xmlData;
> +  } 
> +  
> \ No newline at end of file
> diff --git a/server/views/cimi/machineTemplate/show.html.haml b/server/views/cimi/machineTemplate/show.html.haml
> new file mode 100644
> index 0000000..52aab9c
> --- /dev/null
> +++ b/server/views/cimi/machineTemplate/show.html.haml
> @@ -0,0 +1,79 @@
> +%h1 View/Edit machine template
> +
> +%form{ :action => HOST_API_PATH + "/machineTemplate" }
> +  %input{ :name => :id, :type => :hidden, :value => @dmtfitem["uri"] }/
> +  %input{ :name => :xmlRootNode, :type => :hidden, :value => @xmlRootNode }/
> +  %input{ :name => :refreshURI, :type => :hidden, :value => HOST_API_PATH + "/collection/machineTemplate" }/
> +  %p
> +    %label
> +      Name:
> +  %p
> +    %input{ :name => :name, :size => 50, :value => @dmtfitem["name"], :style => "width:50%;" }
> +    %input{ :name => :created, :type => :hidden, :size => 50, :value => @dmtfitem["created"] }
> +  %p
> +  %br
> +    %label
> +      Description:
> +  %p
> +    %textarea{ :name => :description, :cols => 50, :rows => 4, :style => "width:50%;" } #{@dmtfitem['description']}       
> +  %p
> +  %br
> +    %label
> +      Properties:      
> +  %p
> +    %table{ :style => "width:50%;", :id => "propertyTable"}
> +      - if @dmtfitem["property"]
> +        - if @dmtfitem["property"]["name"] && @dmtfitem["property"]["content"] 
> +          - newPropertyObj = {"#{@dmtfitem['property']['name']}" => {"content" => @dmtfitem["property"]["content"]}}
> +        - else
> +          - newPropertyObj = @dmtfitem["property"]
> +          
> +        - iter = -1
> +        - newPropertyObj.each_pair do |key, value| 
> +          - iter += 1       
> +          %tr
> +            %td
> +              %input{ :name => "param_name_" + iter.to_s, :size => 30, :value => key }                
> +            %td
> +              %input{ :name => "param_value_" + iter.to_s, :size => 30, :value => value["content"] }
> +            %td
> +              %input{ :type => :button, :value => "Remove", :onClick => "return removeProperty(this)" }
> +    %input{ :type => :button, :name => "commit", :value => "Add new property", :onClick => "return AddNewPproperty('propertyTable')" }
> +  %p
> +  %br
> +    %label
> +      TODO Need to handle machineConfiguration
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle machineImage
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle machineAdmins
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle volums
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle volumeTemplates
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle networkInterfaces
> +      
> +  %input{ :type => :button, :name => "commit", :value => "Submit", :onClick => "return doXmlPut(this, true, fixupXml)" }/
> +  %input{ :type => :button, :name => "commit", :value => "Delete", :onClick => "return doXmlDelete(this, true)" }/           
> +              
> +:javascript
> +  function fixupXml(theNode) {
> +    var xmlData = "<?xml version='1.0' encoding='utf-8' ?>";
> +    xmlData += "<" + $(theNode.form).attr("xmlRootNode").value + " xmlns='http://www.dmtf.org/cimi'>";
> +    xmlData += getStandardData(theNode);
> +    xmlData += "</" + $(theNode.form).attr("xmlRootNode").value + ">";
> +    
> +    return xmlData;
> +  } 
> +  
> \ No newline at end of file
> diff --git a/server/views/cimi/system/new.html.haml b/server/views/cimi/system/new.html.haml
> new file mode 100644
> index 0000000..8c01dbd
> --- /dev/null
> +++ b/server/views/cimi/system/new.html.haml
> @@ -0,0 +1,80 @@
> +%h1 Create new system
> +
> +%form{ :action => HOST_API_PATH + "/system" }
> +  %input{ :name => :id, :type => :hidden, :value => @dmtfitem["uri"] }/
> +  %input{ :name => :xmlRootNode, :type => :hidden, :value => @xmlRootNode }/
> +  %input{ :name => :refreshURI, :type => :hidden, :value => HOST_API_PATH + "/collection/system" }/
> +  %p
> +    %label
> +      Name:
> +  %p
> +    %input{ :name => :name, :size => 50, :value => @dmtfitem["name"], :style => "width:50%;" }
> +    %input{ :name => :created, :type => :hidden, :size => 50, :value => @dmtfitem["created"] }
> +  %p
> +  %br
> +    %label
> +      Description:
> +  %p
> +    %textarea{ :name => :description, :cols => 50, :rows => 4, :style => "width:50%;" } #{@dmtfitem['description']}       
> +  %p
> +  %br
> +    %label
> +      Properties:      
> +  %p
> +    %table{ :style => "width:50%;", :id => "propertyTable"}
> +      - if @dmtfitem["property"]
> +        - if @dmtfitem["property"]["name"] && @dmtfitem["property"]["content"] 
> +          - newPropertyObj = {"#{@dmtfitem['property']['name']}" => {"content" => @dmtfitem["property"]["content"]}}
> +        - else
> +          - newPropertyObj = @dmtfitem["property"]
> +          
> +        - iter = -1
> +        - newPropertyObj.each_pair do |key, value| 
> +          - iter += 1       
> +          %tr
> +            %td
> +              %input{ :name => "param_name_" + iter.to_s, :size => 30, :value => key }                
> +            %td
> +              %input{ :name => "param_value_" + iter.to_s, :size => 30, :value => value["content"] }
> +            %td
> +              %input{ :type => :button, :value => "Remove", :onClick => "return removeProperty(this)" }
> +    %input{ :type => :button, :name => "commit", :value => "Add new property", :onClick => "return AddNewPproperty('propertyTable')" }
> +  %p
> +  %br   
> +    %label
> +      State:
> +  %p
> +    = @dmtfitem["state"]
> +    %input{ :name => "state", :type => :hidden, :value => @dmtfitem["state"] }
> +  %br
> +    %label
> +      Status:
> +  %p
> +    %input{ :name => :status, :size => 20, :value => @dmtfitem["status"], :style => "width:50%;" }
> +  %p
> +  %br
> +    %label
> +      TODO Need to handle machines
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle meters
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle eventLog          
> +  %input{ :type => :button, :name => "commit", :value => "Submit", :onClick => "return doXmlPost(this, fixupXml)" }/
> +  %input{ :name => "refresh", :value => false, :type => :hidden}
> +              
> +:javascript
> +  function fixupXml(theNode) {
> +    var xmlData = "<?xml version='1.0' encoding='utf-8' ?>";
> +    xmlData += "<" + $(theNode.form).attr("xmlRootNode").value + " xmlns='http://www.dmtf.org/cimi'>";
> +    xmlData += getStandardData(theNode);
> +    xmlData += "<state>" + $(theNode.form).attr("state").value + "</state>";
> +    xmlData += "<status>" + $(theNode.form).attr("status").value + "</status>";
> +    xmlData += "</" + $(theNode.form).attr("xmlRootNode").value + ">";
> +    
> +    return xmlData;
> +  } 
> +  
> \ No newline at end of file
> diff --git a/server/views/cimi/system/show.html.haml b/server/views/cimi/system/show.html.haml
> new file mode 100644
> index 0000000..324c590
> --- /dev/null
> +++ b/server/views/cimi/system/show.html.haml
> @@ -0,0 +1,80 @@
> +%h1 View/Edit system
> +
> +%form{ :action => HOST_API_PATH + "/system" }
> +  %input{ :name => :id, :type => :hidden, :value => @dmtfitem["uri"] }/
> +  %input{ :name => :xmlRootNode, :type => :hidden, :value => @xmlRootNode }/
> +  %input{ :name => :refreshURI, :type => :hidden, :value => HOST_API_PATH + "/collection/system" }/
> +  %p
> +    %label
> +      Name:
> +  %p
> +    %input{ :name => :name, :size => 50, :value => @dmtfitem["name"], :style => "width:50%;" }
> +    %input{ :name => :created, :type => :hidden, :size => 50, :value => @dmtfitem["created"] }
> +  %p
> +  %br
> +    %label
> +      Description:
> +  %p
> +    %textarea{ :name => :description, :cols => 50, :rows => 4, :style => "width:50%;" } #{@dmtfitem['description']}       
> +  %p
> +  %br
> +    %label
> +      Properties:      
> +  %p
> +    %table{ :style => "width:50%;", :id => "propertyTable"}
> +      - if @dmtfitem["property"]
> +        - if @dmtfitem["property"]["name"] && @dmtfitem["property"]["content"] 
> +          - newPropertyObj = {"#{@dmtfitem['property']['name']}" => {"content" => @dmtfitem["property"]["content"]}}
> +        - else
> +          - newPropertyObj = @dmtfitem["property"]
> +          
> +        - iter = -1
> +        - newPropertyObj.each_pair do |key, value| 
> +          - iter += 1       
> +          %tr
> +            %td
> +              %input{ :name => "param_name_" + iter.to_s, :size => 30, :value => key }                
> +            %td
> +              %input{ :name => "param_value_" + iter.to_s, :size => 30, :value => value["content"] }
> +            %td
> +              %input{ :type => :button, :value => "Remove", :onClick => "return removeProperty(this)" }
> +    %input{ :type => :button, :name => "commit", :value => "Add new property", :onClick => "return AddNewPproperty('propertyTable')" }
> +  %p
> +  %br   
> +    %label
> +      State:
> +  %p
> +    = @dmtfitem["state"]
> +    %input{ :name => "state", :type => :hidden, :value => @dmtfitem["state"] }
> +  %br
> +    %label
> +      Status:
> +  %p
> +    %input{ :name => :status, :size => 20, :value => @dmtfitem["status"], :style => "width:50%;" }
> +  %p
> +  %br
> +    %label
> +      TODO Need to handle machines
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle meters
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle eventLog          
> +  %input{ :type => :button, :name => "commit", :value => "Submit", :onClick => "return doXmlPut(this, true, fixupXml)" }/
> +  %input{ :type => :button, :name => "commit", :value => "Delete", :onClick => "return doXmlDelete(this, true)" }/
> +              
> +:javascript
> +  function fixupXml(theNode) {
> +    var xmlData = "<?xml version='1.0' encoding='utf-8' ?>";
> +    xmlData += "<" + $(theNode.form).attr("xmlRootNode").value + " xmlns='http://www.dmtf.org/cimi'>";
> +    xmlData += getStandardData(theNode);
> +    xmlData += "<state>" + $(theNode.form).attr("state").value + "</state>";
> +    xmlData += "<status>" + $(theNode.form).attr("status").value + "</status>";
> +    xmlData += "</" + $(theNode.form).attr("xmlRootNode").value + ">";
> +    
> +    return xmlData;
> +  } 
> +  
> \ No newline at end of file
> diff --git a/server/views/cimi/system/show.xml.haml b/server/views/cimi/system/show.xml.haml
> new file mode 100644
> index 0000000..b893ffc
> --- /dev/null
> +++ b/server/views/cimi/system/show.xml.haml
> @@ -0,0 +1,11 @@
> +!!!XML
> +%System{ :xmlns => "http://www.dmtf.org/cmp", :"xmlns:atom" => "http://atom.org"}
> +  %uri= HOST_API_PATH + "/system/" + @system.id
> +  %name= @system.name
> +  %timestamp= Time.new.to_i.to_s
> +  %properties
> +  %state= @system.state
> +  %limit= @system.limit  
> +  %atom:link{ :rel => "Machines", :href => HOST_API_PATH + "/machine?system=" + @system.id }
> +  %atom:link{ :rel => "Meters", :href => HOST_API_PATH + "/meter?system=" + @system.id }
> +  %atom:link{ :rel => "EventLog", :href => HOST_API_PATH + "/eventLog?system=" + @system.id }
> diff --git a/server/views/cimi/systemTemplate/new.html.haml b/server/views/cimi/systemTemplate/new.html.haml
> new file mode 100644
> index 0000000..484d08e
> --- /dev/null
> +++ b/server/views/cimi/systemTemplate/new.html.haml
> @@ -0,0 +1,70 @@
> +%h1 Create new system template
> +
> +%form{ :action => HOST_API_PATH + "/systemTemplate" }
> +  %input{ :name => :id, :type => :hidden, :value => @dmtfitem["uri"] }/
> +  %input{ :name => :xmlRootNode, :type => :hidden, :value => @xmlRootNode }/
> +  %input{ :name => :refreshURI, :type => :hidden, :value => HOST_API_PATH + "/collection/systemTemplate" }/
> +  %p
> +    %label
> +      Name:
> +  %p
> +    %input{ :name => :name, :size => 50, :value => @dmtfitem["name"], :style => "width:50%;" }
> +    %input{ :name => :created, :type => :hidden, :size => 50, :value => @dmtfitem["created"] }
> +  %p
> +  %br
> +    %label
> +      Description:
> +  %p
> +    %textarea{ :name => :description, :cols => 50, :rows => 4, :style => "width:50%;" } #{@dmtfitem['description']}       
> +  %p
> +  %br
> +    %label
> +      Properties:      
> +  %p
> +    %table{ :style => "width:50%;", :id => "propertyTable"}
> +      - if @dmtfitem["property"]
> +        - if @dmtfitem["property"]["name"] && @dmtfitem["property"]["content"] 
> +          - newPropertyObj = {"#{@dmtfitem['property']['name']}" => {"content" => @dmtfitem["property"]["content"]}}
> +        - else
> +          - newPropertyObj = @dmtfitem["property"]
> +          
> +        - iter = -1
> +        - newPropertyObj.each_pair do |key, value| 
> +          - iter += 1       
> +          %tr
> +            %td
> +              %input{ :name => "param_name_" + iter.to_s, :size => 30, :value => key }                
> +            %td
> +              %input{ :name => "param_value_" + iter.to_s, :size => 30, :value => value["content"] }
> +            %td
> +              %input{ :type => :button, :value => "Remove", :onClick => "return removeProperty(this)" }
> +    %input{ :type => :button, :name => "commit", :value => "Add new property", :onClick => "return AddNewPproperty('propertyTable')" }
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle volumeTemplates:
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle machineTemplates:
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle networkTemplates:
> +      
> +  %br
> +          
> +  %input{ :type => :button, :name => "commit", :value => "Submit", :onClick => "return doXmlPost(this, fixupXml)" }/
> +  %input{ :name => "refresh", :value => false, :type => :hidden}
> +              
> +:javascript
> +  function fixupXml(theNode) {
> +    var xmlData = "<?xml version='1.0' encoding='utf-8' ?>";
> +    xmlData += "<" + $(theNode.form).attr("xmlRootNode").value + " xmlns='http://www.dmtf.org/cimi'>";
> +    xmlData += getStandardData(theNode);
> +    xmlData += "</" + $(theNode.form).attr("xmlRootNode").value + ">";
> +    
> +    return xmlData;
> +  } 
> +  
> +               
> diff --git a/server/views/cimi/systemTemplate/show.html.haml b/server/views/cimi/systemTemplate/show.html.haml
> new file mode 100644
> index 0000000..7a0613d
> --- /dev/null
> +++ b/server/views/cimi/systemTemplate/show.html.haml
> @@ -0,0 +1,71 @@
> +%h1 View/Edit system template
> +
> +%form{ :action => HOST_API_PATH + "/systemTemplate" }
> +  %input{ :name => :id, :type => :hidden, :value => @dmtfitem["uri"] }/
> +  %input{ :name => :xmlRootNode, :type => :hidden, :value => @xmlRootNode }/
> +  %input{ :name => :refreshURI, :type => :hidden, :value => HOST_API_PATH + "/collection/systemTemplate" }/
> +  %p
> +    %label
> +      Name:
> +  %p
> +    %input{ :name => :name, :size => 50, :value => @dmtfitem["name"], :style => "width:50%;" }
> +    %input{ :name => :created, :type => :hidden, :size => 50, :value => @dmtfitem["created"] }
> +  %p
> +  %br
> +    %label
> +      Description:
> +  %p
> +    %textarea{ :name => :description, :cols => 50, :rows => 4, :style => "width:50%;" } #{@dmtfitem['description']}       
> +  %p
> +  %br
> +    %label
> +      Properties:      
> +  %p
> +    %table{ :style => "width:50%;", :id => "propertyTable"}
> +      - if @dmtfitem["property"]
> +        - if @dmtfitem["property"]["name"] && @dmtfitem["property"]["content"] 
> +          - newPropertyObj = {"#{@dmtfitem['property']['name']}" => {"content" => @dmtfitem["property"]["content"]}}
> +        - else
> +          - newPropertyObj = @dmtfitem["property"]
> +          
> +        - iter = -1
> +        - newPropertyObj.each_pair do |key, value| 
> +          - iter += 1       
> +          %tr
> +            %td
> +              %input{ :name => "param_name_" + iter.to_s, :size => 30, :value => key }                
> +            %td
> +              %input{ :name => "param_value_" + iter.to_s, :size => 30, :value => value["content"] }
> +            %td
> +              %input{ :type => :button, :value => "Remove", :onClick => "return removeProperty(this)" }
> +    %input{ :type => :button, :name => "commit", :value => "Add new property", :onClick => "return AddNewPproperty('propertyTable')" }
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle volumeTemplates:
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle machineTemplates:
> +  %p
> +  %br   
> +    %label
> +      TODO Need to handle networkTemplates:
> +      
> +  %br
> +          
> +  %input{ :type => :button, :name => "commit", :value => "Submit", :onClick => "return doXmlPut(this, fixupXml)" }/
> +  %input{ :type => :button, :name => "commit", :value => "Delete", :onClick => "return doXmlDelete(this, true)" }/
> +  %input{ :name => "refresh", :value => false, :type => :hidden}
> +              
> +:javascript
> +  function fixupXml(theNode) {
> +    var xmlData = "<?xml version='1.0' encoding='utf-8' ?>";
> +    xmlData += "<" + $(theNode.form).attr("xmlRootNode").value + " xmlns='http://www.dmtf.org/cimi'>";
> +    xmlData += getStandardData(theNode);    
> +
> +    xmlData += "</" + $(theNode.form).attr("xmlRootNode").value + ">";
> +    
> +    return xmlData;
> +  } 
> +  
> \ No newline at end of file
> diff --git a/server/views/cimi/test/index.haml b/server/views/cimi/test/index.haml
> new file mode 100644
> index 0000000..0fc2464
> --- /dev/null
> +++ b/server/views/cimi/test/index.haml
> @@ -0,0 +1,9 @@
> +!!!XML
> +%Systems{ :xmlns => "http://www.dmtf.org/cmp", :"xmlns:atom" => "http://atom.org"}
> +  %uri whatever
> +  %name systems
> +  %description systems
> +  %properties
> +  %tongli rocks
> +  %timestamp 
> +    = Time.new.to_i.to_s
> diff --git a/server/views/cimi/test/index.html.haml b/server/views/cimi/test/index.html.haml
> new file mode 100644
> index 0000000..4d6b5bc
> --- /dev/null
> +++ b/server/views/cimi/test/index.html.haml
> @@ -0,0 +1,20 @@
> +%h1
> +  Systems
> +
> +%table.display
> +  %thead
> +    %tr
> +      %th
> +        ID
> +      %th
> +        Name
> +      %th
> +        State
> +      %th
> +        Limit
> +      %th
> +        Machines
> +      %th
> +        Meters
> +      %th
> +        EventLog
> \ No newline at end of file
> diff --git a/server/views/cimi/volumeConfiguration/new.html.haml b/server/views/cimi/volumeConfiguration/new.html.haml
> new file mode 100644
> index 0000000..ee85b0d
> --- /dev/null
> +++ b/server/views/cimi/volumeConfiguration/new.html.haml
> @@ -0,0 +1,75 @@
> +%h1 Create new volume configuration
> +
> +%form{ :action => HOST_API_PATH + "/volumeConfiguration" }
> +  %input{ :name => :id, :type => :hidden, :value => @dmtfitem["uri"] }/
> +  %input{ :name => :xmlRootNode, :type => :hidden, :value => @xmlRootNode }/
> +  %input{ :name => :refreshURI, :type => :hidden, :value => HOST_API_PATH + "/collection/columeConfiguration" }/  
> +  %p
> +    %label
> +      Name:
> +  %p
> +    %input{ :name => :name, :size => 50, :value => @dmtfitem["name"], :style => "width:50%;" }
> +    %input{ :name => :created, :type => :hidden, :size => 50, :value => @dmtfitem["created"] }
> +  %p
> +  %br
> +    %label
> +      Description:
> +  %p
> +    %textarea{ :name => :description, :cols => 50, :rows => 4, :style => "width:50%;" } #{@dmtfitem['description']}       
> +  %p
> +  %br
> +    %label
> +      Properties:      
> +  %p
> +    %table{ :style => "width:50%;", :id => "propertyTable"}
> +      - if @dmtfitem["property"]
> +        - if @dmtfitem["property"]["name"] && @dmtfitem["property"]["content"] 
> +          - newPropertyObj = {"#{@dmtfitem['property']['name']}" => {"content" => @dmtfitem["property"]["content"]}}
> +        - else
> +          - newPropertyObj = @dmtfitem["property"]
> +          
> +        - iter = -1
> +        - newPropertyObj.each_pair do |key, value| 
> +          - iter += 1       
> +          %tr
> +            %td
> +              %input{ :name => "param_name_" + iter.to_s, :size => 30, :value => key }                
> +            %td
> +              %input{ :name => "param_value_" + iter.to_s, :size => 30, :value => value["content"] }
> +            %td
> +              %input{ :type => :button, :value => "Remove", :onClick => "return removeProperty(this)" }
> +    %input{ :type => :button, :name => "commit", :value => "Add new property", :onClick => "return AddNewPproperty('propertyTable')" }
> +  %p
> +  %br   
> +    %label
> +      Format:
> +  %p
> +    %input{ :name => :format, :size => 50, :value => @dmtfitem["format"], :style => "width:50%;" }
> +  %br
> +    %label
> +      Capacity:
> +  %p
> +    %input{ :name => :quantity, :size => 20, :value => @dmtfitem["capacity"]["quantity"], :style => "width:10%;" } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> +    %input{ :name => :units, :size => 20, :value => @dmtfitem["capacity"]["units"], :style => "width:10%;" }
> +  %br
> +    %label
> +      Guest Interface:
> +  %p
> +    %input{ :name => :guestInterface, :size => 50, :value => @dmtfitem["guestInterface"], :style => "width:50%;" }
> +  %br
> +          
> +  %input{ :type => :button, :name => "commit", :value => "Submit", :onClick => "return doXmlPost(this, fixupXml)" }/
> +  %input{ :name => "refresh", :value => false, :type => :hidden}
> +              
> +:javascript
> +  function fixupXml(theNode) {
> +    var xmlData = "<?xml version='1.0' encoding='utf-8' ?>";
> +    xmlData += "<" + $(theNode.form).attr("xmlRootNode").value + " xmlns='http://www.dmtf.org/cimi'>";
> +    xmlData += getStandardData(theNode);
> +    xmlData += "<format>" + $(theNode.form).attr("format").value + "</format>";
> +    xmlData += "<capacity quantity='" + $(theNode.form).attr("quantity").value + "' units='" + $(theNode.form).attr("units").value + "' />";
> +    xmlData += "<guestInterface>" + $(theNode.form).attr("guestInterface").value + "</guestInterface>";
> +    xmlData += "</" + $(theNode.form).attr("xmlRootNode").value + ">";
> +    
> +    return xmlData;
> +  }              
> diff --git a/server/views/cimi/volumeConfiguration/show.html.haml b/server/views/cimi/volumeConfiguration/show.html.haml
> new file mode 100644
> index 0000000..4a7f49a
> --- /dev/null
> +++ b/server/views/cimi/volumeConfiguration/show.html.haml
> @@ -0,0 +1,77 @@
> +%h1 View/Edit Volume configuration
> +
> +%form{ :action => HOST_API_PATH + "/volumeConfiguration" }
> +  %input{ :name => :id, :type => :hidden, :value => @dmtfitem["uri"] }/
> +  %input{ :name => :xmlRootNode, :type => :hidden, :value => @xmlRootNode }/
> +  %input{ :name => :refreshURI, :type => :hidden, :value => HOST_API_PATH + "/collection/columeConfiguration" }/  
> +  %p
> +    %label
> +      Name:
> +  %p
> +    %input{ :name => :name, :size => 50, :value => @dmtfitem["name"], :style => "width:50%;" }
> +    %input{ :name => :created, :type => :hidden, :size => 50, :value => @dmtfitem["created"] }
> +  %p
> +  %br
> +    %label
> +      Description:
> +  %p
> +    %textarea{ :name => :description, :cols => 50, :rows => 4, :style => "width:50%;" } #{@dmtfitem['description']}       
> +  %p
> +  %br
> +    %label
> +      Properties:      
> +  %p
> +    %table{ :style => "width:50%;", :id => "propertyTable"}
> +      - if @dmtfitem["property"]
> +        - if @dmtfitem["property"]["name"] && @dmtfitem["property"]["content"] 
> +          - newPropertyObj = {"#{@dmtfitem['property']['name']}" => {"content" => @dmtfitem["property"]["content"]}}
> +        - else
> +          - newPropertyObj = @dmtfitem["property"]
> +          
> +        - iter = -1
> +        - newPropertyObj.each_pair do |key, value| 
> +          - iter += 1       
> +          %tr
> +            %td
> +              %input{ :name => "param_name_" + iter.to_s, :size => 30, :value => key }                
> +            %td
> +              %input{ :name => "param_value_" + iter.to_s, :size => 30, :value => value["content"] }
> +            %td
> +              %input{ :type => :button, :value => "Remove", :onClick => "return removeProperty(this)" }
> +
> +    %input{ :type => :button, :name => "commit", :value => "Add new property", :onClick => "return AddNewPproperty('propertyTable')" }
> +  %p
> +  %br   
> +    %label
> +      Format:
> +  %p
> +    %input{ :name => :format, :size => 50, :value => @dmtfitem["format"], :style => "width:50%;" }
> +  %br
> +    %label
> +      Capacity:
> +  %p
> +    %input{ :name => :quantity, :size => 20, :value => @dmtfitem["capacity"]["quantity"], :style => "width:10%;" } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
> +    %input{ :name => :units, :size => 20, :value => @dmtfitem["capacity"]["units"], :style => "width:10%;" }
> +  %br
> +    %label
> +      Guest Interface:
> +  %p
> +    %input{ :name => :guestInterface, :size => 50, :value => @dmtfitem["guestInterface"], :style => "width:50%;" }
> +  %br
> +          
> +  %input{ :type => :button, :name => "commit", :value => "Submit", :onClick => "return doXmlPut(this, true, fixupXml)" }/
> +  %input{ :type => :button, :name => "commit", :value => "Delete", :onClick => "return doXmlDelete(this, true)" }/
> +  %input{ :name => "refresh", :value => false, :type => :hidden}
> +              
> +:javascript
> +  function fixupXml(theNode) {
> +    var xmlData = "<?xml version='1.0' encoding='utf-8' ?>";
> +    xmlData += "<" + $(theNode.form).attr("xmlRootNode").value + " xmlns='http://www.dmtf.org/cimi'>";
> +    xmlData += getStandardData(theNode);
> +    xmlData += "<format>" + $(theNode.form).attr("format").value + "</format>";
> +    xmlData += "<capacity quantity='" + $(theNode.form).attr("quantity").value + "' units='" + $(theNode.form).attr("units").value + "' />";
> +    xmlData += "<guestInterface>" + $(theNode.form).attr("guestInterface").value + "</guestInterface>";
> +    xmlData += "</" + $(theNode.form).attr("xmlRootNode").value + ">";
> +    
> +    return xmlData;
> +  }              
> -- 
> 1.7.4.1
> 


Mime
View raw message