cloudstore-developers
Changes
.gitignore 6(+6 -0)
bin/run.py 14(+14 -0)
CHANGES.txt 1(+1 -0)
cloudscale/__init__.py 1(+1 -0)
cloudscale/deployment_scripts/__init__.py 36(+36 -0)
cloudscale/deployment_scripts/backend.py 17(+17 -0)
cloudscale/deployment_scripts/config.py 15(+15 -0)
cloudscale/deployment_scripts/frontend.py 97(+97 -0)
cloudscale/deployment_scripts/logger.py 21(+21 -0)
cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_balancer_instance.py 152(+152 -0)
cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_mongodb_instances.py 293(+293 -0)
cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_mysql_instances.py 349(+349 -0)
cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_showcase_instances.py 366(+366 -0)
cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack-create-instance.py 30(+30 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/AService.java 419(+419 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/BuyConfirmResult.java 42(+42 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/common/ContextHelper.java 22(+22 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/common/DatabaseHelper.java 37(+37 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/common/Soundex.java 92(+92 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/AddressDaoImpl.java 46(+46 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/AuthorDaoImpl.java 64(+64 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/CcXactsDaoImpl.java 67(+67 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/CountryDaoImpl.java 72(+72 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/CustomerDaoImpl.java 75(+75 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/DaoImpl.java 57(+57 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/ItemDaoImpl.java 251(+251 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/OrderLineDaoImpl.java 50(+50 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/OrdersDaoImpl.java 173(+173 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/ShoppingCartDaoImpl.java 83(+83 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/ShoppingCartLineDaoImpl.java 95(+95 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IAddressDao.java 14(+14 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IAuthorDao.java 15(+15 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/ICcXactsDao.java 11(+11 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/ICountryDao.java 14(+14 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/ICustomerDao.java 20(+20 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IDao.java 12(+12 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IItemDao.java 21(+21 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IOrderLineDao.java 13(+13 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IOrdersDao.java 11(+11 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IShoppingCartDao.java 16(+16 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IShoppingCartLineDao.java 18(+18 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/AddressDaoImpl.java 74(+74 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/AuthorDaoImpl.java 82(+82 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/CcXactsDaoImpl.java 78(+78 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/CountryDaoImpl.java 68(+68 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/CustomerDaoImpl.java 80(+80 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/DaoImpl.java 48(+48 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/IDaoExt.java 10(+10 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/ItemDaoImpl.java 232(+232 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/OrderLineDaoImpl.java 63(+63 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/OrdersDaoImpl.java 71(+71 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/ShoppingCartDaoImpl.java 81(+81 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/ShoppingCartLineDaoImpl.java 87(+87 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/IDao.java 25(+25 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/IDaos.java 37(+37 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/IService.java 37(+37 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Address.java 183(+183 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Author.java 156(+156 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/CcXacts.java 187(+187 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Country.java 132(+132 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Customer.java 281(+281 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Item.java 378(+378 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/OrderLine.java 116(+116 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Orders.java 218(+218 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/ShoppingCart.java 87(+87 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/ShoppingCartLine.java 95(+95 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IAddress.java 40(+40 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IAuthor.java 34(+34 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/ICcXacts.java 50(+50 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/ICountry.java 23(+23 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/ICustomer.java 76(+76 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IItem.java 100(+100 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IOrderLine.java 31(+31 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IOrders.java 56(+56 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IShoppingCart.java 20(+20 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IShoppingCartLine.java 24(+24 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Address.java 157(+157 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Author.java 135(+135 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/CcXacts.java 183(+183 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Country.java 93(+93 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Customer.java 283(+283 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Item.java 401(+401 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/OrderLine.java 131(+131 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Orders.java 213(+213 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/ShoppingCart.java 94(+94 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/ShoppingCartLine.java 103(+103 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/services/HibernateService.java 147(+147 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/services/MongoService.java 209(+209 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/AGenerate.java 607(+607 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/Generate.java 71(+71 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/GenerateHibernate.java 169(+169 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/GenerateMongo.java 175(+175 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/IGenerate.java 17(+17 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/AController.java 123(+123 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/BestSellersController.java 41(+41 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/BuyConfirmController.java 143(+143 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/BuyController.java 227(+227 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/CustomerRegistrationController.java 53(+53 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/HomeController.java 102(+102 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/LoginController.java 65(+65 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/NewProductsController.java 76(+76 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/OrderDisplayController.java 92(+92 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/OrderInquiryController.java 56(+56 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/ProductDetailServlet.java 67(+67 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/SearchController.java 83(+83 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/ShoppingCartController.java 114(+114 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/app-context.xml 10(+10 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/database/database.aws.hibernate.properties 6(+6 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/database/database.aws.mongodb.properties 6(+6 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/generate/database.aws.hibernate.properties 6(+6 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/generate/database.properties 6(+6 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/hibernate.xml 98(+98 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/log4j.properties 7(+7 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap.css 6158(+6158 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap.min.css 9(+9 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap-responsive.css 1109(+1109 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap-responsive.min.css 9(+9 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/add_B.gif 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/best_sellers.gif 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/checkout_B.gif 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/display_last_order_B.gif 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/glyphicons-halflings.png 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/glyphicons-halflings-white.png 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/home_B.gif 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/logo-CloudScale.png 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/logo-CloudScale-aws.png 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/order_status_B.gif 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/refresh_B.gif 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/search_B.gif 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/shopping_cart_B.gif 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/submit_B.gif 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/tpclogo.gif 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/update_B.gif 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/whats_new.gif 0(+0 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/js/bootstrap.js 2276(+2276 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/js/bootstrap.min.js 6(+6 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml 59(+59 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/spring/root-context.xml 8(+8 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/best-sellers.html 56(+56 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/buy.html 188(+188 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/buy-confirm.html 71(+71 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/customer-registration.html 87(+87 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/home.html 67(+67 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/login.html 92(+92 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/new-products.html 55(+55 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/order-display.html 112(+112 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/order-inquiry.html 34(+34 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/product_detail.html 61(+61 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/search.html 74(+74 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/shopping-cart.html 79(+79 -0)
cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/templates/layout.html 80(+80 -0)
LICENSE.txt 0(+0 -0)
MANIFEST.in 1(+1 -0)
README.txt 43(+43 -0)
setup.py 19(+19 -0)
Details
.gitignore 6(+6 -0)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0d623d3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+*.pyc
+.idea
+bin/config.ini
+bin/rds-tpcw-dump-latest.sql
+bin/deployment_scripts.log
+bin/paramiko.log
\ No newline at end of file
bin/run.py 14(+14 -0)
diff --git a/bin/run.py b/bin/run.py
new file mode 100644
index 0000000..c4f633c
--- /dev/null
+++ b/bin/run.py
@@ -0,0 +1,14 @@
+import os
+import uuid
+import sys
+from cloudscale.deployment_scripts import deploy
+from cloudscale.deployment_scripts.logger import Logger
+
+if __name__ == "__main__":
+ if len(sys.argv) == 3:
+ config_path = sys.argv[2]
+ infrastructure = sys.argv[1]
+ logger = Logger()
+ deploy(config_path, os.path.abspath(os.path.dirname(__file__)), logger)
+ else:
+ print """Usage: python run.py <aws|openstack> <path_to_config>"""
\ No newline at end of file
CHANGES.txt 1(+1 -0)
diff --git a/CHANGES.txt b/CHANGES.txt
new file mode 100644
index 0000000..27b2995
--- /dev/null
+++ b/CHANGES.txt
@@ -0,0 +1 @@
+v1, 2015-02-24 -- Initial release
cloudscale/__init__.py 1(+1 -0)
diff --git a/cloudscale/__init__.py b/cloudscale/__init__.py
new file mode 100644
index 0000000..8f76346
--- /dev/null
+++ b/cloudscale/__init__.py
@@ -0,0 +1 @@
+__author__ = 'ivansek'
cloudscale/deployment_scripts/__init__.py 36(+36 -0)
diff --git a/cloudscale/deployment_scripts/__init__.py b/cloudscale/deployment_scripts/__init__.py
new file mode 100644
index 0000000..041edd7
--- /dev/null
+++ b/cloudscale/deployment_scripts/__init__.py
@@ -0,0 +1,36 @@
+import os
+import uuid
+from cloudscale.deployment_scripts.backend import Backend
+from cloudscale.deployment_scripts.config import Config
+from cloudscale.deployment_scripts.frontend import Frontend
+from cloudscale.deployment_scripts.scripts.infrastructure.openstack import openstack_remove_all
+
+
+def deploy(config_path, results_dir, logger):
+ config = Config(results_dir, config_path)
+ _setup_backend(config, logger)
+ _setup_frontend(config, logger)
+
+def _setup_backend(config, logger):
+ backend = Backend(config, logger)
+
+ if config.provider == 'aws':
+ backend.setup_rds()
+ else:
+ openstack_remove_all.RemoveAll(config, logger)
+ if config.db_provider == 'mysql':
+ backend.setup_openstack_mysql()
+ else:
+ backend.setup_openstack_mongodb()
+
+
+def _setup_frontend(config, logger):
+ frontend = Frontend(config, logger)
+
+ showcase_url = None
+ if config.provider == 'aws':
+ showcase_url = frontend.setup_aws_frontend()
+ elif config.provider == 'openstack':
+ showcase_url = frontend.setup_openstack_frontend()
+
+ logger.log('You can view your showcase on <a href="http://%s/showcase-1-a">http://%s/showcase-1-a</a>' % (showcase_url, showcase_url), fin=True)
cloudscale/deployment_scripts/backend.py 17(+17 -0)
diff --git a/cloudscale/deployment_scripts/backend.py b/cloudscale/deployment_scripts/backend.py
new file mode 100644
index 0000000..7ca7173
--- /dev/null
+++ b/cloudscale/deployment_scripts/backend.py
@@ -0,0 +1,17 @@
+from cloudscale.deployment_scripts.scripts.infrastructure.openstack import openstack_create_mysql_instances
+from cloudscale.deployment_scripts.scripts.platform.aws import configure_rds
+from cloudscale.deployment_scripts.scripts.infrastructure.openstack import openstack_create_mongodb_instances
+class Backend:
+
+ def __init__(self, config, logger):
+ self.config = config
+ self.logger = logger
+
+ def setup_rds(self):
+ configure_rds.ConfigureRDS(self.config, self.logger)
+
+ def setup_openstack_mysql(self):
+ openstack_create_mysql_instances.ConfigureMySQL(self.config, self.logger)
+
+ def setup_openstack_mongodb(self):
+ openstack_create_mongodb_instances.ConfigureMongodb(self.config, self.logger)
\ No newline at end of file
cloudscale/deployment_scripts/config.py 15(+15 -0)
diff --git a/cloudscale/deployment_scripts/config.py b/cloudscale/deployment_scripts/config.py
new file mode 100644
index 0000000..ea83afd
--- /dev/null
+++ b/cloudscale/deployment_scripts/config.py
@@ -0,0 +1,15 @@
+from cloudscale.deployment_scripts.scripts import read_config, create_user_path
+
+
+class Config:
+
+ def __init__(self, output_directory, config_path):
+ self.config_path = config_path
+ self.user_path = create_user_path(output_directory)
+ self.cfg = read_config(self.config_path)
+ self.provider = self.cfg.get('COMMON', 'provider')
+ self.db_provider = self.cfg.get('COMMON', 'db_provider')
+
+ def save(self, section, variable, value):
+ self.cfg.save_option(self.config_path, section, variable, str(value))
+
cloudscale/deployment_scripts/frontend.py 97(+97 -0)
diff --git a/cloudscale/deployment_scripts/frontend.py b/cloudscale/deployment_scripts/frontend.py
new file mode 100644
index 0000000..b08e01d
--- /dev/null
+++ b/cloudscale/deployment_scripts/frontend.py
@@ -0,0 +1,97 @@
+import os
+import time
+from cloudscale.deployment_scripts.scripts.infrastructure.aws import aws_create_keypair
+from cloudscale.deployment_scripts.scripts.infrastructure.aws import aws_create_instance
+from cloudscale.deployment_scripts.scripts.infrastructure.aws import aws_create_loadbalancer
+from cloudscale.deployment_scripts.scripts.software import deploy_showcase
+from cloudscale.deployment_scripts.scripts.infrastructure.aws import aws_create_ami
+from cloudscale.deployment_scripts.scripts.infrastructure.aws import aws_create_autoscalability
+from cloudscale.deployment_scripts.scripts.infrastructure.openstack import openstack_create_showcase_instances
+from cloudscale.deployment_scripts.scripts.infrastructure.openstack import openstack_create_balancer_instance
+
+
+
+class Frontend:
+
+ def __init__(self, config, logger):
+ self.config = config
+ self.logger=logger
+
+ def setup_aws_frontend(self):
+ self.logger=self.logger
+ self.cfg = self.config.cfg
+ self.config = self.config
+ self.file_path = "/".join(os.path.abspath(__file__).split('/')[:-1])
+ self.showcase_location = self.cfg.get('MYSQL', 'showcase_war_url')
+ self.config.save('infrastructure', 'remote_user', self.cfg.get('EC2', 'remote_user'))
+ self.remote_user = self.cfg.get('infrastructure', 'remote_user')
+ self.remote_deploy_path = self.cfg.get('software', 'remote_deploy_path')
+ self.db_num_instances = int(self.cfg.get('RDS', 'num_replicas')) + 1
+ self.database_name = self.cfg.get('RDS', 'database_name')
+ self.database_user = self.cfg.get('RDS', 'database_user')
+ self.database_pass = self.cfg.get('RDS', 'database_pass')
+ self.deploy_name = "showcase-1-a"
+ self.connection_pool_size = self.cfg.get('RDS', 'connection_pool_size')
+
+ i = aws_create_keypair.CreateKeyPair(
+ cfg=self.cfg,
+ user_path=self.config.user_path
+ )
+ i.create()
+
+ self.config.save('EC2', 'key_pair', "%s/%s.pem" % (self.config.user_path, self.config.cfg.get('EC2', 'key_name')))
+
+ self.key_pair = self.cfg.get('EC2', 'key_pair')
+ showcase_url = None
+ if self.cfg.get('EC2', 'is_autoscalable') == 'no':
+ instances = []
+ i = aws_create_instance.CreateEC2Instance(cfg=self.config.cfg, logger=self.logger)
+ ip_addresses = []
+ num_instances = int(self.cfg.get('COMMON', 'num_instances'))
+ for _ in xrange(num_instances):
+ instance = i.create()
+ instances.append(instance)
+ ip_addresses.append(instance.ip_address)
+
+ self.config.save('infrastructure', 'ip_address', ','.join(ip_addresses))
+
+
+
+ self.ip_addresses = self.cfg.get('infrastructure', 'ip_address').split(",")
+ loadbalancer = None
+ if len(instances) > 1:
+ i = aws_create_loadbalancer.CreateLoadbalancer(
+ instances=instances,
+ config=self.config,
+ logger=self.logger
+ )
+ loadbalancer = i.create()
+
+ deploy_showcase.DeploySoftware(self)
+
+ showcase_url = loadbalancer.dns_name if loadbalancer else instances[0].ip_address
+
+ elif self.cfg.get('EC2', 'is_autoscalable') == 'yes':
+ i = aws_create_instance.CreateEC2Instance(cfg=self.config.cfg, logger=self.logger)
+ instance = i.create()
+ self.config.save('infrastructure', 'ip_address', instance.ip_address)
+ self.config.save('infrastructure', 'remote_user', 'ubuntu')
+ self.ip_addresses = self.cfg.get('infrastructure', 'ip_address').split(",")
+
+ deploy_showcase.DeploySoftware(self)
+
+ aws_create_ami.EC2CreateAMI(config=self.config, logger=self.logger)
+
+ autoscalability = aws_create_autoscalability.Autoscalability(
+ cfg=self.cfg,
+ logger=self.logger
+ )
+ showcase_url = autoscalability.create()
+
+ time.sleep(60)
+ return showcase_url
+
+ def setup_openstack_frontend(self):
+ openstack_create_showcase_instances.CreateInstance(self.config, self.logger)
+ public_ip = openstack_create_balancer_instance.CreateInstance(self.config, self.logger).get_public_ip()
+ return public_ip
cloudscale/deployment_scripts/logger.py 21(+21 -0)
diff --git a/cloudscale/deployment_scripts/logger.py b/cloudscale/deployment_scripts/logger.py
new file mode 100644
index 0000000..aa5046e
--- /dev/null
+++ b/cloudscale/deployment_scripts/logger.py
@@ -0,0 +1,21 @@
+import logging
+logging.basicConfig(filename='deployment_scripts.log')
+
+class Logger:
+ def __init__(self):
+ pass
+
+ def info(self, msg):
+ logging.info(msg)
+
+ def log(self, msg, level=logging.INFO, append_to_last=False, fin=False):
+ logging.log(level, msg)
+
+ def debug(self, msg):
+ logging.debug(msg)
+
+ def error(self, msg):
+ logging.error(msg)
+
+ def warning(self, msg):
+ logging.warning(msg)
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/__init__.py b/cloudscale/deployment_scripts/scripts/__init__.py
new file mode 100644
index 0000000..6dab0fc
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/__init__.py
@@ -0,0 +1,39 @@
+import os
+import sys
+import uuid
+import boto
+from cloudscale.deployment_scripts.logger import Logger
+
+
+def usage(args):
+ print 'Usage:\n $ python %s %s' % (sys.argv[0].split("/")[-1], args)
+
+def check_args(num_args, args_desc):
+ if len(sys.argv) < num_args+1:
+ usage(args_desc)
+ exit(0)
+
+def create_user_path(output_directory):
+ user_id = uuid.uuid4()
+ path = "%s/%s" % (output_directory, user_id)
+
+ if not os.path.exists(path):
+ os.makedirs(path)
+
+ return path
+
+
+def get_cfg_logger(output_directory, config_path):
+ cfg = read_config(config_path)
+
+ path = create_user_path(output_directory)
+
+ logger = Logger()
+ return path, cfg, logger
+
+
+def read_config(config_file):
+ cfg = boto.Config()
+ cfg.load_from_path(os.path.abspath(config_file))
+
+ return cfg
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/infrastructure/__init__.py b/cloudscale/deployment_scripts/scripts/infrastructure/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/infrastructure/__init__.py
diff --git a/cloudscale/deployment_scripts/scripts/infrastructure/aws/__init__.py b/cloudscale/deployment_scripts/scripts/infrastructure/aws/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/infrastructure/aws/__init__.py
diff --git a/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_create_ami.py b/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_create_ami.py
new file mode 100644
index 0000000..79927d8
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_create_ami.py
@@ -0,0 +1,89 @@
+# from common.Cloudscale import *
+import boto.ec2
+import time
+import sys
+from cloudscale.deployment_scripts.scripts import check_args, get_cfg_logger
+
+
+class EC2CreateAMI:
+
+ def __init__(self, config, logger):
+ self.logger = logger
+ self.cfg = config.cfg
+ self.config = config
+ self.key_name = self.cfg.get('EC2', 'key_name')
+ self.key_pair = self.cfg.get('EC2', 'key_pair')
+ self.conn = boto.ec2.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+
+ ami_id = self.create_ami(self.cfg.get('infrastructure', 'ip_address'))
+ self.config.save('infrastructure', 'ami_id', ami_id)
+ self.logger.log("Done")
+
+ def create_ami(self, instance_ip):
+ self.logger.log("Creating AMI from instance %s" % instance_ip)
+ if instance_ip is None:
+ self.logger.log("instance_ip is null")
+ exit(0)
+
+ instance_id = None
+ for instance in self.conn.get_only_instances():
+ if instance.ip_address == instance_ip:
+ instance_id = instance.id
+ break
+
+ if instance_id is None:
+ self.logger.log("Can't find any instances to create ami from!")
+ exit(0)
+ try:
+ image_id = self.conn.create_image(instance_id, 'cloudscale-as-image')
+ self.wait_available(image_id)
+ self.terminate_instance(instance_id)
+ return image_id
+ except boto.exception.EC2ResponseError as e:
+ if str(e.error_code) == 'InvalidAMIName.Duplicate':
+ image = self.conn.get_all_images(filters={'name' : 'cloudscale-as-image'})[0]
+ image.deregister()
+ return self.create_ami(instance_ip)
+ self.logger.log("Error creating AMI image")
+ exit(0)
+
+ def terminate_instance(self, instance_id):
+ self.conn.terminate_instances([instance_id])
+ self.wait_terminate(instance_id)
+
+ def wait_available(self, image_id):
+ self.logger.log("Waiting to create AMI from instance ..")
+ status = self.conn.get_all_images(image_ids=[image_id])[0].state
+ i=1
+ while status != 'available':
+ if i%10 == 0:
+ self.logger.log("\nPlease wait .")
+ self.logger.log(".", append_to_last=True)
+ status = self.conn.get_all_images(image_ids=[image_id])[0].state
+ time.sleep(3)
+ i=i+1
+
+ self.logger.log("Done")
+
+ def wait_terminate(self, instance_id):
+ self.logger.log("Waiting for instance to terminate\nPlease wait ..")
+ status = self.conn.get_all_instances([instance_id])[0].instances[0].state
+ i=1
+ while status != 'terminated':
+ if i%10 == 0:
+ self.logger.log("\nPlease wait .")
+ self.logger.log(".", append_to_last=True)
+ status = self.conn.get_all_instances([instance_id])[0].instances[0].state
+ time.sleep(3)
+ i=i+1
+
+ self.logger.log("Instance is terminated!")
+
+if __name__ == "__main__":
+ check_args(2, "<output_dir> <config_path>")
+ user_path, cfg, logger = get_cfg_logger(sys.argv[1], sys.argv[2])
+ EC2CreateAMI(cfg, logger)
+
+
diff --git a/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_create_autoscalability.py b/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_create_autoscalability.py
new file mode 100644
index 0000000..e5546ac
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_create_autoscalability.py
@@ -0,0 +1,150 @@
+import boto.ec2.elb
+import boto.ec2.autoscale
+from boto.ec2.autoscale import AutoScalingGroup
+from boto.ec2.autoscale import LaunchConfiguration
+from boto.ec2.autoscale import ScalingPolicy
+import boto.ec2.cloudwatch
+from boto.ec2.cloudwatch import MetricAlarm
+import sys
+from cloudscale.deployment_scripts.scripts import check_args, get_cfg_logger
+
+
+class Autoscalability:
+ def __init__(self, cfg, logger):
+ self.cfg = cfg
+ self.logger = logger
+ self.key_pair=self.cfg.get('EC2', 'key_pair')
+ self.key_name=self.cfg.get('EC2', 'key_name')
+
+ def create(self):
+ self.conn = boto.ec2.autoscale.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+ lb = self.create_load_balancer()
+ self.create_security_group('http', 'Security group for HTTP', '0.0.0.0/0', '80')
+ self.create_security_group('ssh', 'Security group for SSH', '0.0.0.0/0', '22')
+
+ lc = self.create_launch_configuration()
+ self.create_autoscalability_group(lb.name, lc)
+ scale_up_policy_arn, scale_down_policy_arn = self.create_scaling_policy()
+ self.create_cloudwatch_alarms(scale_up_policy_arn, scale_down_policy_arn)
+ return lb.dns_name
+
+ def create_cloudwatch_alarms(self, scale_up_policy_arn, scale_down_policy_arn):
+ self.logger.log("Creating CloudWatch alarms ...")
+
+ conn = boto.ec2.cloudwatch.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+ alarm_dimensions = {'AutoScalingGroupName' : 'cloudscale-as'}
+
+ scale_up_alarm = MetricAlarm(
+ name='scale_up_on_cpu', namespace='AWS/EC2',
+ metric='CPUUtilization', statistic='Average',
+ comparison='>', threshold='70',
+ period='60', evaluation_periods=1,
+ alarm_actions=[scale_up_policy_arn],
+ dimensions=alarm_dimensions)
+
+ scale_down_alarm = MetricAlarm(
+ name='scale_down_on_cpu', namespace='AWS/EC2',
+ metric='CPUUtilization', statistic='Average',
+ comparison='<', threshold='20',
+ period='60', evaluation_periods=1,
+ alarm_actions=[scale_down_policy_arn],
+ dimensions=alarm_dimensions)
+
+ conn.create_alarm(scale_up_alarm)
+ conn.create_alarm(scale_down_alarm)
+
+ def create_scaling_policy(self):
+ self.logger.log("Creating scaling policy ...")
+ scale_up_policy = ScalingPolicy(name='scale_up',
+ adjustment_type='ChangeInCapacity',
+ as_name='cloudscale-as',
+ scaling_adjustment=1,
+ cooldown=int(self.cfg.get('EC2', 'cooldown'))
+ )
+ scale_down_policy = ScalingPolicy(name='scale_down',
+ adjustment_type='ChangeInCapacity',
+ as_name='cloudscale-as',
+ scaling_adjustment=-1,
+ cooldown=int(self.cfg.get('EC2', 'cooldown'))
+ )
+ self.conn.create_scaling_policy(scale_up_policy)
+ self.conn.create_scaling_policy(scale_down_policy)
+ scale_up_policy = self.conn.get_all_policies(
+ as_group='cloudscale-as', policy_names=['scale_up'])[0]
+ scale_down_policy = self.conn.get_all_policies(
+ as_group='cloudscale-as', policy_names=['scale_down'])[0]
+
+ return scale_up_policy.policy_arn, scale_down_policy.policy_arn
+
+ def create_launch_configuration(self):
+ self.logger.log("Creating launch configuration ...")
+
+ try:
+ lc = LaunchConfiguration(self.conn,
+ "cloudscale-lc",
+ self.cfg.get('infrastructure', 'ami_id'),
+ self.key_name,
+ ['http'],
+ None,
+ self.cfg.get('EC2', 'instance_type'),
+ instance_monitoring=True)
+
+ self.conn.create_launch_configuration(lc)
+ return lc
+ except boto.exception.BotoServerError as e:
+ if e.error_code == 'AlreadyExists':
+ return self.conn.get_all_launch_configurations(names=['cloudscale-lc'])
+ else:
+ raise
+
+ def create_autoscalability_group(self, lb_name, lc):
+ self.logger.log("Creating autoscalability group ...")
+
+ try:
+ ag = AutoScalingGroup(group_name='cloudscale-as',
+ load_balancers=[lb_name],
+ availability_zones=self.cfg.get('EC2', 'availability_zones').split(","),
+ launch_config=lc, min_size=1, max_size=10, connection=self.conn)
+ self.conn.create_auto_scaling_group(ag)
+ except boto.exception.BotoServerError as e:
+ if e.error_code != 'AlreadyExists':
+ raise # self.conn.get_all_groups(names=['cloudscale-as'])[0]
+
+
+ def create_security_group(self, name, description, cidr, port):
+ try:
+ conn = boto.ec2.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+ conn.create_security_group(name, description)
+ conn.authorize_security_group(group_name=name, ip_protocol='tcp', from_port=port, to_port=port, cidr_ip=cidr)
+
+ conn.create_dbsecurity_group(name, description)
+ conn.authorize_dbsecurity_group(name, cidr, name)
+ except boto.exception.EC2ResponseError as e:
+ if str(e.error_code) != 'InvalidGroup.Duplicate':
+ raise
+
+ def create_load_balancer(self):
+ self.logger.log("Creating load balancer ...")
+ conn = boto.ec2.elb.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+
+ zones = self.cfg.get('EC2', 'availability_zones').split(",")
+ ports = [(80, 80, 'http')]
+
+ lb = conn.create_load_balancer('cloudscale-lb', zones, ports)
+
+ return lb
+
+
+if __name__ == "__main__":
+ check_args(2, "<config_path>")
+ user_path, cfg, logger = get_cfg_logger(sys.argv[1], sys.argv[2])
+
+ Autoscalability(cfg, logger)
diff --git a/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_create_instance.py b/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_create_instance.py
new file mode 100644
index 0000000..5187808
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_create_instance.py
@@ -0,0 +1,87 @@
+import boto, boto.exception
+import boto, boto.ec2
+import boto.manage.cmdshell
+import time
+import paramiko
+
+import sys, os
+from cloudscale.deployment_scripts.scripts import check_args, get_cfg_logger
+
+
+class CreateEC2Instance:
+
+ def __init__(self, cfg, logger):
+ self.key_pair = cfg.get('EC2', 'key_pair')
+ self.key_name = cfg.get('EC2', 'key_name')
+ self.cfg = cfg
+ self.conn = boto.ec2.connect_to_region(
+ self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key')
+ )
+ self.logger = logger
+
+
+ def create(self):
+ self.create_security_groups()
+ instance = self.create_instance()
+ #self.write_config(instance)
+ self.logger.log(instance.id)
+ return instance
+
+ def create_security_groups(self):
+ self.logger.log("Creating security groups http and ssh ...")
+ self.create_security_group('http', 'Security group for HTTP protocol', '80', '0.0.0.0/0')
+ self.create_security_group('ssh', 'Security group for HTTP protocol', '22', '0.0.0.0/0')
+
+ def create_security_group(self, name, description, port, cidr):
+ try:
+ self.conn.create_security_group(name, description)
+ self.conn.authorize_security_group(group_name=name, ip_protocol='tcp', from_port=port, to_port=port, cidr_ip=cidr)
+ except boto.exception.EC2ResponseError as e:
+ if str(e.error_code) != 'InvalidGroup.Duplicate':
+ raise
+
+ def create_instance(self):
+ self.logger.log("Creating EC2 instance ...")
+ res = self.conn.run_instances(
+ self.cfg.get('EC2', 'ami_id'),
+ key_name=self.key_name,
+ instance_type=self.cfg.get('EC2','instance_type'),
+ security_groups=['http', 'ssh'],
+ placement=self.cfg.get('EC2', 'availability_zones').split(',')[0]
+ )
+ self.wait_available(res.instances[0])
+
+ instance = self.conn.get_all_instances([res.instances[0].id])[0].instances[0]
+ self.conn.monitor_instances([instance.id])
+ return instance
+
+ def wait_available(self, instance):
+ self.logger.log("Waiting for instance to become available\nPlease wait . .")
+ status = self.conn.get_all_instances([instance.id])[0].instances[0].state
+ i=1
+ while status != 'running':
+ if i%10 == 0:
+ self.logger.log("\nPlease wait .")
+ self.logger.log(".", append_to_last=True)
+ status = self.conn.get_all_instances([instance.id])[0].instances[0].state
+ time.sleep(3)
+ i=i+1
+
+ self.logger.log("Instance is running!")
+
+
+ def write_config(self, instance):
+ self.cfg.save_user_option('infrastructure', 'remote_user', 'ubuntu')
+ self.cfg.save_user_option('infrastructure', 'ip_address', instance.ip_address)
+ # f = open(os.path.abspath('../infrastructure.ini'), 'w')
+ # f.write('[EC2]\n')
+ # f.write('remote_user=ubuntu\n')
+ # f.write('ip_address=' + instance.ip_address + '\n')
+ # f.close()
+
+if __name__ == '__main__':
+ check_args(2, "<config_path>")
+ user_path, cfg, logger = get_cfg_logger(sys.argv[1], sys.argv[2])
+ CreateEC2Instance(cfg, logger)
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_create_keypair.py b/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_create_keypair.py
new file mode 100644
index 0000000..84347f5
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_create_keypair.py
@@ -0,0 +1,35 @@
+from boto import ec2
+import os
+from boto.exception import EC2ResponseError
+import sys
+from cloudscale.deployment_scripts.scripts import check_args, get_cfg_logger
+
+
+class CreateKeyPair:
+
+ def __init__(self, user_path, cfg):
+ self.cfg = cfg
+ self.user_path = user_path
+
+ def create(self):
+ conn = ec2.connect_to_region(
+ self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key')
+ )
+
+ try:
+ keypair = conn.create_key_pair(self.cfg.get('EC2', 'key_name'))
+ except EC2ResponseError as e:
+ if e.error_code == 'InvalidKeyPair.Duplicate':
+ conn.delete_key_pair(key_name=self.cfg.get('EC2', 'key_name') )
+ keypair = conn.create_key_pair(self.cfg.get('EC2', 'key_name'))
+ else:
+ raise e
+
+ keypair.save(self.user_path)
+
+if __name__ == '__main__':
+ check_args(2, "<config_path>")
+ user_path, cfg, logger = get_cfg_logger(sys.argv[1], sys.argv[2])
+ CreateKeyPair(user_path, cfg)
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_create_loadbalancer.py b/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_create_loadbalancer.py
new file mode 100644
index 0000000..bc780f0
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_create_loadbalancer.py
@@ -0,0 +1,54 @@
+from boto import ec2
+from boto.exception import BotoServerError
+import sys
+from cloudscale.deployment_scripts.scripts import check_args, get_cfg_logger
+
+
+class CreateLoadbalancer:
+
+ def __init__(self, instances, config, logger):
+ self.instances = instances
+ self.cfg = config.cfg
+ self.config = config
+ self.logger = logger
+
+
+ def create(self):
+ self.logger.log("Creating load balancer ...")
+ conn = ec2.elb.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+
+ zones = self.cfg.get('EC2', 'availability_zones').split(",")
+ ports = [(80, 80, 'http')]
+
+
+
+ lb_name = 'cloudscale-lb'
+ try:
+ lb = conn.get_all_load_balancers(load_balancer_names=[lb_name])
+ except BotoServerError as e:
+ lb =[]
+
+ i = 2
+ while len(lb) > 0:
+ lb_name = 'cloudscale-lb-%s' % i
+ try:
+ lb = conn.get_all_load_balancers(load_balancer_names=[lb_name])
+ except BotoServerError as e:
+ lb = []
+ i+=1
+
+ lb = conn.create_load_balancer(lb_name, zones, ports)
+
+ self.attach_instances(lb)
+
+ return lb
+
+ def attach_instances(self, lb):
+ lb.register_instances([i.id for i in self.instances])
+
+if __name__ == '__main__':
+ check_args(2, "<config_path>")
+ user_path, cfg, logger = get_cfg_logger(sys.argv[1], sys.argv[2])
+ CreateLoadbalancer(cfg, logger)
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_remove_all.py b/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_remove_all.py
new file mode 100644
index 0000000..55a0bf8
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/infrastructure/aws/aws_remove_all.py
@@ -0,0 +1,248 @@
+import boto.ec2.elb
+import boto.rds
+import boto.ec2.autoscale
+from boto.ec2.autoscale import AutoScalingGroup
+from boto.ec2.autoscale import LaunchConfiguration
+from boto.ec2.autoscale import ScalingPolicy
+import boto.ec2.cloudwatch
+from boto.exception import BotoServerError
+from boto.ec2.cloudwatch import MetricAlarm
+import time
+import sys
+from cloudscale.deployment_scripts.scripts import check_args, get_cfg_logger
+
+
+class RemoveAll:
+ def __init__(self, cfg, logger):
+ self.cfg = cfg
+ self.logger = logger
+ self.key_name = self.cfg.get('EC2', 'key_name')
+ self.key_pair = self.cfg.get('EC2', 'key_pair')
+ self.conn_ec2 = boto.ec2.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+ self.conn_as = boto.ec2.autoscale.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+ self.remove_cloudwatch_alarms()
+
+ self.remove_load_balancer()
+ self.remove_ami()
+ self.remove_ec2_instances()
+ self.remove_autoscale_group()
+ self.remove_launch_configuration()
+ self.remove_rds_instances()
+ # self.remove_security_groups()
+
+ self.logger.log("Done")
+
+ def remove_rds_instances(self):
+ self.logger.log("Removing RDS instances ..")
+ conn = boto.rds.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+
+ try:
+ conn.delete_dbinstance(id='cloudscale-master', skip_final_snapshot=True)
+ except BotoServerError as e:
+ import traceback
+ self.logger.log(traceback.format_exc())
+ self.logger.log(e.message)
+
+ num = self.cfg.get('RDS', 'num_replicas')
+ for i in xrange(int(num)):
+ try:
+ conn.delete_dbinstance(id='cloudscale-replica%s' % str(i+1), skip_final_snapshot=True)
+ except BotoServerError as e:
+ import traceback
+ self.logger.log(traceback.format_exc())
+ self.logger.log(e.message)
+
+ def remove_ec2_instances(self):
+ self.logger.log("Terminating EC2 instances ...")
+
+ group = self.conn_as.get_all_groups(['cloudscale-as'])
+ instance_ids = []
+ if len(group) > 0:
+ instance_ids = [i.instance_id for i in group[0].instances]
+
+ if len(instance_ids) > 0:
+ self.conn_ec2.terminate_instances(instance_ids=instance_ids)
+ for instance_id in instance_ids:
+ self.wait_terminate(instance_id)
+
+ def wait_terminate(self, instance_id):
+ self.logger.log("Waiting for instance to terminate\nPlease wait . .")
+ status = self.conn_ec2.get_all_instances([instance_id])[0].instances[0].state
+ i=1
+ while status != 'terminated':
+ if i%10 == 0:
+ self.logger.log("\nPlease wait .")
+ self.logger.log(".", append_to_last=True)
+ status = self.conn_ec2.get_all_instances([instance_id])[0].instances[0].state
+ time.sleep(3)
+ i=i+1
+
+ self.logger.log("Instance is terminated!")
+
+ def remove_autoscale_group(self):
+ self.logger.log("Removing autoscale group ...")
+ try:
+ self.conn_as.delete_auto_scaling_group('cloudscale-as')
+ except BotoServerError as e:
+ import traceback
+ self.logger.log(traceback.format_exc())
+ self.logger.log(e.message)
+
+
+ def remove_launch_configuration(self):
+ self.logger.log("Removing launch configuration ..")
+ try:
+ self.conn_as.delete_launch_configuration('cloudscale-lc')
+ except BotoServerError as e:
+ import traceback
+ self.logger.log(traceback.format_exc())
+ self.logger.log(e.message)
+
+ def remove_cloudwatch_alarms(self):
+ self.logger.log("Removing cloudwatch alarms ...")
+ conn_cw = boto.ec2.cloudwatch.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+ conn_cw.delete_alarms(['scale_up_on_cpu', 'scale_down_on_cpu'])
+
+ def remove_security_groups(self):
+ self.logger.log("Removing security groups ...")
+ self.conn_ec2.delete_security_group('ssh')
+ self.conn_ec2.delete_security_group('http')
+
+ def remove_load_balancer(self):
+ self.logger.log("Removing load balancer ...")
+ conn_elb = boto.ec2.elb.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+ conn_elb.delete_load_balancer('cloudscale-lb')
+
+ def remove_ami(self):
+ self.logger.log("Removing ami ...")
+ try:
+ self.conn_ec2.deregister_image(self.cfg.get('infrastructure', 'ami_id'))
+ except:
+ pass
+
+ def create_cloudwatch_alarms(self, scale_up_policy_arn, scale_down_policy_arn):
+ self.logger.log("Creating CloudWatch alarms")
+
+ conn = boto.ec2.cloudwatch.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+ alarm_dimensions = {'AutoScalingGroupName' : 'cloudscale-as'}
+
+ scale_up_alarm = MetricAlarm(
+ name='scale_up_on_cpu', namespace='AWS/EC2',
+ metric='CPUUtilization', statistic='Average',
+ comparison='>', threshold='70',
+ period='60', evaluation_periods=2,
+ alarm_actions=[scale_up_policy_arn],
+ dimensions=alarm_dimensions)
+
+ scale_down_alarm = MetricAlarm(
+ name='scale_down_on_cpu', namespace='AWS/EC2',
+ metric='CPUUtilization', statistic='Average',
+ comparison='<', threshold='40',
+ period='60', evaluation_periods=2,
+ alarm_actions=[scale_down_policy_arn],
+ dimensions=alarm_dimensions)
+
+ conn.create_alarm(scale_up_alarm)
+ conn.create_alarm(scale_down_alarm)
+
+ def create_scaling_policy(self):
+ self.logger.log("Creating scaling policy ...")
+ scale_up_policy = ScalingPolicy(name='scale_up',
+ adjustment_type='ChangeInCapacity',
+ as_name='cloudscale-as',
+ scaling_adjustment=2,
+ cooldown=180
+ )
+ scale_down_policy = ScalingPolicy(name='scale_down',
+ adjustment_type='ChangeInCapacity',
+ as_name='cloudscale-as',
+ scaling_adjustment=-2,
+ cooldown=180)
+ self.conn.create_scaling_policy(scale_up_policy)
+ self.conn.create_scaling_policy(scale_down_policy)
+ scale_up_policy = self.conn.get_all_policies(
+ as_group='cloudscale-as', policy_names=['scale_up'])[0]
+ scale_down_policy = self.conn.get_all_policies(
+ as_group='cloudscale-as', policy_names=['scale_down'])[0]
+
+ return scale_up_policy.policy_arn, scale_down_policy.policy_arn
+
+ def create_launch_configuration(self):
+ self.logger.log("Creating launch configuration ...")
+
+ try:
+ lc = LaunchConfiguration(self.conn,
+ "cloudscale-lc",
+ self.cfg.get('infrastructure', 'ami_id'),
+ self.key_name,
+ ['http'],
+ None,
+ self.cfg.get('EC2', 'instance_type'))
+
+ self.conn.create_launch_configuration(lc)
+ return lc
+ except boto.exception.BotoServerError as e:
+ if e.error_code == 'AlreadyExists':
+ return self.conn.get_all_launch_configurations(names=['cloudscale-lc'])
+ else:
+ raise
+
+ def create_autoscalability_group(self, lb_name, lc):
+ self.logger.log("Creating autoscalability group ...")
+
+ try:
+ ag = AutoScalingGroup(group_name='cloudscale-as',
+ load_balancers=[lb_name],
+ availability_zones=self.cfg.get('EC2', 'availability_zones').split(","),
+ launch_config=lc, min_size=2, max_size=8, connection=self.conn)
+ self.conn.create_auto_scaling_group(ag)
+ except boto.exception.BotoServerError as e:
+ if e.error_code != 'AlreadyExists':
+ raise # self.conn.get_all_groups(names=['cloudscale-as'])[0]
+
+
+ def create_security_group(self, name, description, cidr, port):
+ try:
+ conn = boto.ec2.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+ conn.create_security_group(name, description)
+ conn.authorize_security_group(group_name=name, ip_protocol='tcp', from_port=port, to_port=port, cidr_ip=cidr)
+
+ conn.create_dbsecurity_group(name, description)
+ conn.authorize_dbsecurity_group(name, cidr, name)
+ except boto.exception.EC2ResponseError as e:
+ if str(e.error_code) != 'InvalidGroup.Duplicate':
+ raise
+
+ def create_load_balancer(self):
+ self.logger.log("Creating load balancer ...")
+ conn = boto.ec2.elb.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+
+ zones = self.cfg.get('EC2', 'availability_zones').split(",")
+ ports = [(80, 80, 'http')]
+
+ lb = conn.create_load_balancer('cloudscale-lb', zones, ports)
+
+ return lb.name
+
+
+if __name__ == "__main__":
+ check_args(2, "<output_dir> <config_path>")
+ path, cfg, logger = get_cfg_logger(sys.argv[1], sys.argv[2])
+
+ RemoveAll(cfg, logger)
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/infrastructure/openstack/__init__.py b/cloudscale/deployment_scripts/scripts/infrastructure/openstack/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/infrastructure/openstack/__init__.py
diff --git a/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_balancer_instance.py b/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_balancer_instance.py
new file mode 100644
index 0000000..c4fa133
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_balancer_instance.py
@@ -0,0 +1,152 @@
+import base64
+import os
+from novaclient.v2 import client as novaclient
+import time
+import sys
+from cloudscale.deployment_scripts.scripts import check_args, get_cfg_logger
+
+
+class CreateInstance:
+
+ def __init__(self, config, logger):
+ self.cfg = config.cfg
+ self.config = config
+ self.logger = logger
+
+ self.user = self.cfg.get('OPENSTACK', 'username')
+ self.pwd = self.cfg.get('OPENSTACK', 'password')
+ self.url = self.cfg.get('OPENSTACK', 'auth_url')
+ self.tenant = self.cfg.get('OPENSTACK', 'tenant_name')
+
+ self.image_name = self.cfg.get('OPENSTACK', 'image_name')
+
+ self.instance_type = self.cfg.get('OPENSTACK', 'instance_type')
+ self.instance_name = 'cloudscale-lb'
+ self.num_instances = self.config.fr.get('num_instances')
+ self.key_name = self.cfg.get('OPENSTACK', 'key_name')
+ self.key_pair = self.cfg.get('OPENSTACK', 'key_pair')
+
+ self.database_type = self.cfg.get('OPENSTACK', 'database_type').lower()
+
+ self.nc = novaclient.Client(self.user, self.pwd, self.tenant, auth_url=self.url)
+
+ showcase_servers = self.nc.servers.findall(name="cloudscale-sc")
+
+ if len(showcase_servers) == 1:
+ self.logger.log("Only one instance")
+ server_id = showcase_servers[0].id
+ self.load_balancer_public_ip = self.add_floating_ip(server_id)
+ self.add_security_group(server_id, "ssh")
+ return
+
+ self.logger.log("Creating load balancer instance:")
+
+ self.file_path = os.path.dirname(__file__) + "/../../software"
+
+ ha_proxy_config = open(self.file_path + '/haproxy.cfg', 'r').read()
+ checker = base64.b64encode(open(self.file_path + '/check-running-showcase_instances.py', 'r').read())
+ openstack_config = base64.b64encode(open(self.config.config_path, 'r').read())
+
+ #############################################################################################################
+ # TODO: remove this when instances can connect to openstack, as servers will be automatically added by script
+ # add showcase servers to config
+ for server in showcase_servers:
+ for address in server.addresses[server.addresses.keys()[0]]:
+ if address['OS-EXT-IPS:type'] == 'fixed':
+ server_ip = address['addr']
+ break
+ else:
+ server_ip = None
+ self.logger.log("Error: can not get IP address")
+ ha_proxy_config += """
+ server %s %s:8080 check""" % (server_ip, server_ip)
+ #############################################################################################################
+
+ userdata = open(self.file_path + '/install-load-balancer.sh', 'r').read()
+ userdata = ha_proxy_config.join(
+ userdata.split("#####REPLACE_ME_WITH_CONFIG#####")
+ )
+ userdata = checker.join(
+ userdata.split("###PLACEHOLDER_FOR_checker.py###")
+ )
+ userdata = openstack_config.join(
+ userdata.split("###PLACEHOLDER_FOR_config.ini###")
+ )
+
+ server_id = self.create_instance(userdata=userdata)
+
+ self.add_security_group(server_id, "ssh")
+ self.add_security_group(server_id, "http")
+
+ self.load_balancer_public_ip = self.add_floating_ip(server_id)
+
+ self.logger.log('Done creating load balancer instance')
+
+ def get_public_ip(self):
+ return self.load_balancer_public_ip
+
+ def create_instance(self, image_name=None, files=None, userdata=None, wait_on_active_status=True):
+ if image_name is None:
+ image_name = self.image_name
+
+ for f in self.nc.flavors.list():
+ if f.name == self.instance_type:
+ flavor = f
+ break
+ else:
+ self.logger.log("Instance flavor '%s' not found!" % self.instance_type)
+ return False
+
+ for img in self.nc.images.list():
+ if img.name == image_name:
+ image = img
+ break
+ else:
+ self.logger.log("Image '%s' not found!" % image_name)
+ return False
+
+ server_id = self.nc.servers.create(
+ self.instance_name, image, flavor, key_name=self.key_name, files=files, userdata=userdata
+ ).id
+
+ if wait_on_active_status and not self.wait_active(server_id):
+ return False
+
+ return server_id
+
+ def wait_active(self, server_id):
+ self.logger.log("Waiting for instance to be built . . .")
+ status = self.wait_for_instance_status(server_id, u'BUILD', u'ACTIVE')
+ if not status:
+ self.logger.log("Can not start instance %s!" % self.instance_name)
+ return False
+ return True
+
+ def wait_for_instance_status(self, server_id, current_status, wait_for_status):
+ while True:
+ server = self.nc.servers.get(server_id)
+ if server.status != current_status:
+ if server.status == wait_for_status:
+ return True
+ return False
+ time.sleep(1)
+
+ def add_floating_ip(self, server_id):
+ server = self.nc.servers.get(server_id)
+ unallocated_floating_ips = self.nc.floating_ips.findall(fixed_ip=None)
+ if len(unallocated_floating_ips) < 1:
+ unallocated_floating_ips.append(self.nc.floating_ips.create())
+ floating_ip = unallocated_floating_ips[0]
+ server.add_floating_ip(floating_ip)
+ return floating_ip.ip
+
+ def add_security_group(self, server_id, group_name):
+ self.logger.log("Adding security group %s" % group_name)
+ server = self.nc.servers.get(server_id)
+ server.add_security_group(group_name)
+
+
+if __name__ == '__main__':
+ check_args(2, "<output_dir> <config_path>")
+ path, cfg, logger = get_cfg_logger(sys.argv[1], sys.argv[2])
+ CreateInstance(cfg, logger)
diff --git a/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_mongodb_instances.py b/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_mongodb_instances.py
new file mode 100644
index 0000000..274b968
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_mongodb_instances.py
@@ -0,0 +1,293 @@
+import os
+from novaclient.v2 import client as novaclient
+import time
+import paramiko
+
+class ConfigureMongodb:
+
+ def __init__(self, config, logger):
+ self.cfg = config.cfg
+ self.config = config
+ self.logger = logger
+
+ self.user = self.cfg.get('OPENSTACK', 'username')
+ self.pwd = self.cfg.get('OPENSTACK', 'password')
+ self.url = self.cfg.get('OPENSTACK', 'auth_url')
+ self.tenant = self.cfg.get('OPENSTACK', 'tenant_name')
+
+ self.image_name = self.cfg.get('OPENSTACK', 'image_name')
+
+ self.instance_type = self.cfg.get('MONGODB', 'instance_type')
+ self.instance_name = 'cloudscale-db-mongo'
+ self.num_replicas = self.cfg.get('MONGODB', 'num_replicas')
+
+ self.key_name = self.cfg.get('OPENSTACK', 'key_name')
+ self.key_pair = self.cfg.get('OPENSTACK', 'key_pair')
+
+ self.mongodb_image_name = "cloudscale-db-mongo-image"
+
+ self.database_name = self.cfg.get('MONGODB', 'database_name')
+ self.database_user = self.cfg.get('MONGODB', 'database_user')
+ self.database_pass = self.cfg.get('MONGODB', 'database_pass')
+
+ self.generate_dump_path = self.cfg.get('MONGODB', 'generate_dump_path')
+
+ self.database_type = self.cfg.get('OPENSTACK', 'database_type').lower()
+
+ self.remote_user = self.cfg.get('OPENSTACK', 'image_username')
+
+ self.nc = novaclient.Client(self.user, self.pwd, self.tenant, auth_url=self.url)
+
+ self.logger.log("Creating database instances:")
+ images = self.nc.images.list()
+ for image in images:
+ if image.name == self.mongodb_image_name:
+ self.logger.log('Image already exists.')
+ break
+ else:
+ self.file_path = os.path.dirname(__file__) + "/../../software"
+
+ userdata = """#!/bin/bash
+USERNAME=%s
+""" % self.remote_user + open(self.file_path + '/install-mongodb.sh', 'r').read()
+
+ server_id = self.create_instance(userdata=userdata)
+ self.wait_powered_off(server_id)
+ self.create_image(server_id, self.mongodb_image_name)
+ self.delete_instance(server_id)
+
+ self.logger.log("Done creating database image")
+
+ database_server_ids = self.create_database_instances()
+
+ self.start_mongo_on_instances(database_server_ids)
+
+ self.logger.log('Done creating database instances')
+
+ def delete_instance(self, server_id):
+ self.logger.log("Deleting instance ...")
+ server = self.nc.servers.get(server_id)
+ server.delete()
+
+ def create_instance(self, image_name=None, userdata=None, wait_on_active_status=True):
+ if image_name is None:
+ image_name = self.image_name
+
+ for f in self.nc.flavors.list():
+ if f.name == self.instance_type:
+ flavor = f
+ break
+ else:
+ self.logger.log("Instance flavor '%s' not found!" % self.instance_type)
+ return False
+
+ for img in self.nc.images.list():
+ if img.name == image_name:
+ image = img
+ break
+ else:
+ self.logger.log("Image '%s' not found!" % image_name)
+ return False
+
+ server_id = self.nc.servers.create(self.instance_name, image, flavor, key_name=self.key_name, userdata=userdata).id
+
+ if wait_on_active_status and not self.wait_active(server_id):
+ return False
+
+ return server_id
+
+ def wait_active(self, server_id):
+ self.logger.log("Waiting for instance to be built . . .")
+ status = self.wait_for_instance_status(server_id, u'BUILD', u'ACTIVE')
+ if not status:
+ self.logger.log("Can not start instance %s!" % self.instance_name)
+ return False
+ return True
+
+ def wait_all_instances_active(self, instance_ids):
+ for instance_id in instance_ids:
+ self.wait_active(instance_id)
+
+ def wait_powered_off(self, server_id):
+ self.logger.log("Waiting for instance %s to be powered off . . ." % server_id)
+ status = self.wait_for_instance_status(server_id, u'ACTIVE', u'SHUTOFF')
+ if not status:
+ self.logger.log("Error on instance %s!" % self.instance_name)
+ return False
+ return True
+
+ def wait_for_instance_status(self, server_id, current_status, wait_for_status):
+ while True:
+ server = self.nc.servers.get(server_id)
+ if server.status != current_status:
+ if server.status == wait_for_status:
+ return True
+ return False
+ time.sleep(1)
+
+ def add_floating_ip(self, server_id):
+ server = self.nc.servers.get(server_id)
+ unallocated_floating_ips = self.nc.floating_ips.findall(fixed_ip=None)
+ if len(unallocated_floating_ips) < 1:
+ unallocated_floating_ips.append(self.nc.floating_ips.create())
+ floating_ip = unallocated_floating_ips[0]
+ server.add_floating_ip(floating_ip)
+ return floating_ip.ip
+
+ def remove_floating_ip(self, server_id, floating_ip):
+ server = self.nc.servers.get(server_id)
+ server.remove_floating_ip(floating_ip)
+
+ def add_security_group(self, server_id, group_name):
+ self.logger.log("Adding security group %s" % group_name)
+ server = self.nc.servers.get(server_id)
+ server.add_security_group(group_name)
+
+ def create_image(self, server_id, image_name):
+ self.logger.log("Creating image ...")
+ server = self.nc.servers.get(server_id)
+ image_id = server.create_image(image_name)
+
+ while True:
+ image = self.nc.images.get(image_id)
+ if image.status == u'ACTIVE':
+ return True
+ if image.status == u'ERROR':
+ self.logger.log("Error creating image!")
+ return False
+ time.sleep(3)
+
+ def create_database_instances(self):
+ database_server_ids = []
+
+ for i in range(int(self.num_replicas)):
+ self.logger.log("Creating database instance %s ..." % (i + 1))
+ database_server_ids.append(
+ self.create_instance(image_name=self.mongodb_image_name, wait_on_active_status=False)
+ )
+
+ self.wait_all_instances_active(database_server_ids)
+ return database_server_ids
+
+ def upload_mongo_dump(self, ip_address):
+ self.logger.log("Connecting to ssh on %s" % ip_address)
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ while True:
+ try:
+ ssh.connect(ip_address, username=self.remote_user, key_filename=os.path.abspath(self.key_pair))
+ break
+ except:
+ time.sleep(5)
+
+ scp = paramiko.SFTPClient.from_transport(ssh.get_transport())
+ self.logger.log("Uploading mysql dump")
+ scp.put(self.generate_dump_path, 'dump.sql')
+
+ ssh.exec_command("sudo mv dump.sql /root/dump.sql")
+
+ def get_ip(self, server_id):
+ server = self.nc.servers.get(server_id)
+
+ for address in server.addresses[server.addresses.keys()[0]]:
+ if address['OS-EXT-IPS:type'] == 'fixed':
+ server_ip = address['addr']
+ break
+ else:
+ server_ip = None
+ self.logger.log("Error: can not get IP address of this server")
+ return server_ip
+
+ def ssh_execute_command(self, ssh, command):
+ transport = ssh.get_transport()
+ channel = transport.open_session()
+ channel.exec_command(command)
+ return channel.recv_exit_status()
+
+ def start_mongo_on_instances(self, database_server_ids):
+ self.logger.log("Creating ssh connections")
+ ssh_connections = [] # (server_id, ip_address, ssh, floating_ip)
+ for server_id in database_server_ids:
+ self.add_security_group(server_id, 'mongo')
+ self.add_security_group(server_id, 'ssh')
+ floating_ip = self.add_floating_ip(server_id)
+
+ self.logger.log("Connecting to ssh on %s" % floating_ip)
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ while True:
+ try:
+ ssh.connect(floating_ip, username=self.remote_user, key_filename=os.path.abspath(self.key_pair))
+ break
+ except:
+ time.sleep(5)
+
+ ssh_connections.append((server_id, self.get_ip(server_id), ssh, floating_ip))
+
+ config_servers = []
+
+ self.logger.log("Starting config servers")
+ num_config_servers = 3 if len(ssh_connections) >= 3 else 1
+ for i in range(num_config_servers):
+ config_servers.append(ssh_connections[i][1] + ":27019")
+ ssh = ssh_connections[i][2]
+ self.ssh_execute_command(
+ ssh,
+ """sudo mkdir -p /data/configdb
+sudo mongod --configsvr --dbpath /data/configdb --port 27019 --syslog --fork""")
+
+ config_servers = ','.join(config_servers)
+
+ self.logger.log("Starting mongos")
+ for i in range(len(ssh_connections)):
+ ssh = ssh_connections[i][2]
+ self.ssh_execute_command(ssh, "sudo mongos --configdb %s --syslog --fork" % config_servers)
+
+ self.logger.log("Adding shards")
+ for i in range(len(ssh_connections)):
+ ssh = ssh_connections[i][2]
+ fixed_ip = ssh_connections[i][1]
+ self.ssh_execute_command(ssh, """echo 'sh.addShard("%s:27037")' | mongo""" % fixed_ip)
+
+ # only on one server
+ ssh = ssh_connections[0][2]
+
+ self.logger.log("Configuring sharding for database and collections")
+ self.ssh_execute_command(ssh, """echo 'sh.enableSharding("%s")' | mongo""" % self.database_name)
+ collections = ['address', 'author', 'ccxacts', 'customer', 'item', 'orderLine',
+ 'orderLineMR', 'orders', 'shoppingCart', 'shoppingCartLine']
+ default_shard_key_pattern = '{ "_id": "hashed" }'
+ for collection in collections:
+ shard_key_pattern = default_shard_key_pattern
+ self.ssh_execute_command(ssh, """echo 'sh.shardCollection("%s.%s", %s )' | mongo"""
+ % (self.database_name, collection, shard_key_pattern))
+
+ scp = paramiko.SFTPClient.from_transport(ssh.get_transport())
+ self.logger.log("Uploading mongo dump")
+ scp.put(self.generate_dump_path, 'dump.tar.gz')
+
+ self.logger.log("Extracting mongo dump")
+ self.ssh_execute_command(ssh, "mkdir dump; tar xf dump.tar.gz -C dump")
+
+ self.logger.log("Importing mongo dump")
+ self.ssh_execute_command(ssh, "mongorestore --db tpcw dump/tpcw/")
+
+ self.logger.log("Removing dump.tar.gz and folder dump/")
+ self.ssh_execute_command(ssh, "rm dump.tar.gz; rm -r dump")
+
+ self.logger.log("Creating user")
+ self.ssh_execute_command(ssh, """echo 'db.createUser({
+ "user": "%s",
+ "pwd": "%s",
+ "roles": [ { "role": "readWrite", "db": "%s" } ]
+})' | mongo %s""" % (self.database_user, self.database_pass, self.database_name, self.database_name))
+
+ self.logger.log("Close ssh connections, and removing public IPs and ssh security groups")
+ for i in range(len(ssh_connections)):
+ server_id = ssh_connections[i][0]
+ fixed_ip = ssh_connections[i][1]
+ ssh = ssh_connections[i][2]
+ floating_ip = ssh_connections[i][3]
+ ssh.close()
+ self.remove_floating_ip(server_id, floating_ip)
+
diff --git a/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_mysql_instances.py b/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_mysql_instances.py
new file mode 100644
index 0000000..3232e67
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_mysql_instances.py
@@ -0,0 +1,349 @@
+import os
+from novaclient.v2 import client as novaclient
+import time
+import paramiko
+import select
+import sys
+from cloudscale.deployment_scripts.scripts import check_args, get_cfg_logger
+
+
+class ConfigureMySQL:
+
+ def __init__(self, config, logger):
+ self.cfg = config.cfg
+ self.config = config
+ self.logger = logger
+
+ self.user = self.cfg.get('OPENSTACK', 'username')
+ self.pwd = self.cfg.get('OPENSTACK', 'password')
+ self.url = self.cfg.get('OPENSTACK', 'auth_url')
+ self.tenant = self.cfg.get('OPENSTACK', 'tenant_name')
+
+
+
+ self.instance_type = self.cfg.get('MYSQL', 'instance_type')
+ self.instance_name = 'cloudscale-db'
+ self.master_instance_name = 'cloudscale-db-master'
+ self.num_replicas = self.cfg.get('MYSQL', 'num_replicas')
+
+ self.key_name = self.cfg.get('OPENSTACK', 'key_name')
+ self.key_pair = self.cfg.get('OPENSTACK', 'key_pair')
+
+ self.galera_image_name = "cloudscale-db-image"
+
+ self.database_name = self.cfg.get('MYSQL', 'database_name')
+ self.database_user = self.cfg.get('MYSQL', 'database_user')
+ self.database_pass = self.cfg.get('MYSQL', 'database_pass')
+
+ self.generate_dump_path = self.cfg.get('MYSQL', 'generate_dump_path')
+
+ self.database_type = self.cfg.get('OPENSTACK', 'database_type').lower()
+
+
+
+ self.nc = novaclient.Client(self.user, self.pwd, self.tenant, auth_url=self.url)
+
+
+
+ self.logger.log("Creating database instances:")
+ self.file_path = os.path.dirname(__file__) + "/../../software"
+
+ if self.config.db.get('setup_type') == 'master-slave':
+ self.image_name = self.cfg.get('MYSQL', 'image_name')
+ self.remote_user = self.cfg.get('MYSQL', 'image_username')
+ self.create_master_slave()
+ elif self.config.db.get('setup_type') == 'master-master':
+ self.image_name = self.cfg.get('OPENSTACK', 'image_name')
+ self.remote_user = self.cfg.get('OPENSTACK', 'image_username')
+ self.create_master_master()
+
+
+ def create_master_master(self):
+ images = self.nc.images.list()
+ for image in images:
+ if image.name == self.galera_image_name:
+ self.logger.log('Image already exists.')
+ break
+ else:
+
+ userdata = """#!/bin/bash
+DB_NAME=%s
+DB_USERNAME=%s
+DB_PASSWORD=%s
+""" % (self.database_name, self.database_user, self.database_pass) + """
+USERNAME=%s
+""" % self.remote_user + open(self.file_path + '/install-mysql-galera.sh', 'r').read() + """
+echo '
+""" + open(self.file_path + '/my.cnf', 'r').read().replace("'", "\"'\"") + """
+' > /etc/mysql/my.cnf
+""" + open(self.file_path + '/install-mysql-galera-import-dump.sh', 'r').read()
+
+ server_id = self.create_instance(userdata=userdata)
+ floating_ip = self.add_floating_ip(server_id)
+ self.add_security_group(server_id, "ssh")
+ self.upload_mysql_dump(floating_ip)
+
+ self.wait_powered_off(server_id)
+ self.create_image(server_id, self.galera_image_name)
+ self.delete_instance(server_id)
+
+ self.logger.log("Done creating database image")
+
+ self.create_database_instances()
+
+ self.logger.log('Done creating database instances')
+
+ def create_master_slave(self):
+ master_ip, master_private_ip = self.create_master()
+ slaves = self.create_slave(master_private_ip, int(self.num_replicas)-1)
+ self.upload_mysql_dump(master_ip)
+ ssh = self.ssh_to_instance(master_ip)
+ _ ,stdout, _ = ssh.exec_command("mysql -u root -ppassword -D tpcw < ~/dump.sql")
+ self.wait_for_command(stdout, True)
+ self.config.save('platform', 'urls', master_private_ip + ',' + ",".join([private_ip for _, private_ip in slaves]) )
+
+ def create_master(self):
+ tmp_instance_name = self.instance_name
+ self.instance_name = self.master_instance_name
+
+ server_id = self.create_instance(image_name=self.image_name)
+ time.sleep(40)
+ self.instance_name = tmp_instance_name
+
+ floating_ip = self.add_floating_ip(server_id)
+ self.add_security_group(server_id, "mysql")
+ ssh = self.ssh_to_instance(floating_ip);
+
+ self.scp_file(self.file_path+"/master_slave/my.cnf.master", "my.cnf", ssh)
+ self.scp_file(self.file_path+"/master_slave/setup_master.sh", "setup_master.sh", ssh)
+ _, stdout, _ = ssh.exec_command("sudo mv ~/my.cnf /etc/mysql/my.cnf; sh ~/setup_master.sh")
+ #self.wait_for_command(stdout, True)
+ foo = stdout.readlines()
+ if len(foo) > 0:
+ self.master_file, self.master_position = foo[2].split("|")
+
+ ssh.close()
+ private_ip = self.nc.servers.get(server_id)._info.get('addresses').get(self.tenant)[0].get('addr')
+ return floating_ip, private_ip
+ raise Exception("Can't get master_file and master_position")
+
+ def create_slave(self, master_ip, num_replicas):
+ slaves = [self.create_slave_instance(image_name=self.image_name) for _ in xrange(num_replicas)]
+ i = 2
+ for ip, _ in slaves:
+ ssh = self.ssh_to_instance(ip)
+ self.scp_file(self.file_path+"/master_slave/my.cnf.slave", "my.cnf", ssh)
+ _, stdout,_ = ssh.exec_command("sudo mv ~/my.cnf /etc/mysql/my.cnf; sudo sed -i 's/^#server-id\s\+= 1$/server-id = %s/g' /etc/mysql/my.cnf" % i)
+ self.wait_for_command(stdout, True)
+ _, stdout, _ = ssh.exec_command("""sudo service mysql restart; mysql -u root -ppassword -e "STOP SLAVE;" """)
+ self.wait_for_command(stdout, True)
+ cmd = '''mysql -u root -ppassword -e "CHANGE MASTER TO MASTER_HOST='%s',MASTER_USER='slave_user', MASTER_PASSWORD='password', MASTER_LOG_FILE='%s', MASTER_LOG_POS= %s;"''' % (master_ip, self.master_file, self.master_position)
+ f = open("tmp.sh", "w")
+ f.write(cmd)
+ f.close()
+ self.scp_file("tmp.sh", "tmp.sh", ssh)
+ _, stdout, _ = ssh.exec_command("sh tmp.sh")
+ self.wait_for_command(stdout, True)
+ cmd = "mysql -u root -ppassword -e \"CREATE DATABASE tpcw\""
+ _, stdout, _ = ssh.exec_command(cmd)
+ self.wait_for_command(stdout, True)
+
+ cmd = "mysql -u root -ppassword -e \"GRANT ALL ON tpcw.* TO 'root'@'%' IDENTIFIED BY 'password'\""
+
+ _, stdout, _ = ssh.exec_command(cmd)
+ self.wait_for_command(stdout, True)
+
+ _, stdout, _ = ssh.exec_command("mysql -u root -ppassword -e \"START SLAVE;\"")
+ ssh.close()
+ i+=1
+ return slaves
+
+ def create_slave_instance(self, image_name=None):
+ server_id = self.create_instance(image_name=image_name)
+ time.sleep(10)
+ floating_ip = self.add_floating_ip(server_id)
+ self.add_security_group(server_id, "mysql")
+ private_ip = self.get_private_ip(server_id)
+ return floating_ip, private_ip
+
+ def get_private_ip(self,server_id, i=0):
+ try:
+ return self.nc.servers.get(server_id)._info.get('addresses').get(self.tenant)[0].get('addr')
+ except Exception as e:
+ if i<3:
+ return self.get_private_ip(server_id, i+1)
+ else:
+ raise e
+
+ def scp_file(self, file, remote_file, ssh):
+ scp = paramiko.SFTPClient.from_transport(ssh.get_transport())
+ scp.put(file, remote_file)
+
+ def delete_instance(self, server_id):
+ self.logger.log("Deleting instance ...")
+ server = self.nc.servers.get(server_id)
+ server.delete()
+
+ def create_instance(self, image_name=None, userdata=None, wait_on_active_status=True):
+ if image_name is None:
+ image_name = self.image_name
+
+ flavor = self.nc.flavors.find(name=self.instance_type)
+
+ if flavor is None:
+ self.logger.log("Instance flavor '%s' not found!" % self.instance_type)
+ return False
+
+ image = self.nc.images.find(name=image_name)
+ if image is None:
+ self.logger.log("Image '%s' not found!" % image_name)
+ return False
+
+ net = self.nc.networks.find(label=self.tenant)
+ nics = [{'net-id' : net.id}]
+
+ server_id = self.nc.servers.create(self.instance_name, image, flavor, key_name=self.key_name, userdata=userdata, nics=nics).id
+
+ #if wait_on_active_status and not self.wait_active(server_id):
+ # return False
+
+ return server_id
+
+ def wait_active(self, server_id):
+ self.logger.log("Waiting for instance to be built . . .")
+ status = self.wait_for_instance_status(server_id, u'BUILD', u'ACTIVE')
+ if not status:
+ self.logger.log("Can not start instance %s!" % self.instance_name)
+ return False
+ return True
+
+ def wait_all_instances_active(self, instance_ids):
+ for instance_id in instance_ids:
+ self.wait_active(instance_id)
+
+ def wait_powered_off(self, server_id):
+ self.logger.log("Waiting for instance %s to be powered off . . ." % server_id)
+ status = self.wait_for_instance_status(server_id, u'ACTIVE', u'SHUTOFF')
+ if not status:
+ self.logger.log("Error on instance %s!" % self.instance_name)
+ return False
+ return True
+
+ def wait_for_instance_status(self, server_id, current_status, wait_for_status):
+ while True:
+ server = self.nc.servers.get(server_id)
+ if server.status != current_status:
+ if server.status == wait_for_status:
+ return True
+ return False
+ time.sleep(1)
+
+ def add_floating_ip(self, server_id):
+ server = self.nc.servers.get(server_id)
+ unallocated_floating_ips = self.nc.floating_ips.findall(fixed_ip=None)
+ if len(unallocated_floating_ips) < 1:
+ unallocated_floating_ips.append(self.nc.floating_ips.create())
+ floating_ip = unallocated_floating_ips[0]
+ server.add_floating_ip(floating_ip)
+ return floating_ip.ip
+
+ def add_security_group(self, server_id, group_name):
+ self.logger.log("Adding security group %s" % group_name)
+ server = self.nc.servers.get(server_id)
+ server.add_security_group(group_name)
+
+ def create_image(self, server_id, image_name):
+ self.logger.log("Creating image ...")
+ server = self.nc.servers.get(server_id)
+ image_id = server.create_image(image_name)
+
+ while True:
+ image = self.nc.images.get(image_id)
+ if image.status == u'ACTIVE':
+ return True
+ if image.status == u'ERROR':
+ self.logger.log("Error creating image!")
+ return False
+ time.sleep(3)
+
+ def create_database_instances(self):
+ self.logger.log("Creating first instance ...")
+
+ database_server_ids = []
+
+ userdata = open(self.file_path + '/start-mysql-galera-first-node.sh', 'r').read()
+
+ server_id = self.create_instance(image_name=self.galera_image_name, userdata=userdata)
+ database_server_ids.append(server_id)
+ time.sleep(10)
+ server = self.nc.servers.get(server_id)
+ for address in server.addresses[server.addresses.keys()[0]]:
+ if address['OS-EXT-IPS:type'] == 'fixed':
+ server_ip = address['addr']
+ break
+ else:
+ server_ip = None
+ self.logger.log("Error: can not get IP address of first node")
+ self.logger.log("IP address of first node: %s" % server_ip)
+
+ userdata = """#!/bin/bash
+FIRST_NODE_IP=%s
+""" % server_ip + open(self.file_path + '/start-mysql-galera-other-nodes.sh', 'r').read()
+
+ for i in range(int(self.num_replicas) - 1):
+ self.logger.log("Creating database instance %s ..." % (i + 2))
+ database_server_ids.append(
+ self.create_instance(image_name=self.galera_image_name, userdata=userdata, wait_on_active_status=False)
+ )
+
+ self.wait_all_instances_active(database_server_ids)
+
+ for server_id in database_server_ids:
+ self.add_security_group(server_id, 'galera')
+
+ def wait_for_command(self, stdout, verbose=False):
+ # Wait for the command to terminate
+ while not stdout.channel.exit_status_ready():
+ # Only print data if there is data to read in the channel
+ if stdout.channel.recv_ready():
+ rl, wl, xl = select.select([stdout.channel], [], [], 0.0)
+ if len(rl) > 0:
+ response = stdout.channel.recv(1024)
+ if verbose:
+ print response
+
+
+ def ssh_to_instance(self, ip_addr):
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ while True:
+ try:
+ ssh.connect(ip_addr, username=self.remote_user, key_filename=os.path.abspath(self.key_pair))
+ break
+ except:
+ time.sleep(5)
+ return ssh
+
+ def upload_mysql_dump(self, ip_address):
+ self.logger.log("Connecting to ssh on %s" % ip_address)
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ while True:
+ try:
+ ssh.connect(ip_address, username=self.remote_user, key_filename=os.path.abspath(self.key_pair))
+ break
+ except:
+ time.sleep(5)
+
+ #scp = paramiko.SFTPClient.from_transport(ssh.get_transport())
+ self.logger.log("Uploading mysql dump")
+ #scp.put(self.generate_dump_path, 'dump.sql')
+ ssh.exec_command("wget -q -T90 http://cloudscale.xlab.si/github/rds-tpcw-dump-latest.sql -O dump.sql")
+
+ ssh.exec_command("touch finished")
+
+
+if __name__ == '__main__':
+ check_args(2, "<output_dir> <config_path>")
+ path, cfg, logger = get_cfg_logger(sys.argv[1], sys.argv[2])
+ ConfigureMySQL(cfg, logger)
diff --git a/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_showcase_instances.py b/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_showcase_instances.py
new file mode 100644
index 0000000..8c8c4e9
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_create_showcase_instances.py
@@ -0,0 +1,366 @@
+import os
+import subprocess
+from novaclient.v2 import client as novaclient
+import time
+import paramiko
+import select
+from cloudscale.deployment_scripts.scripts import check_args, get_cfg_logger
+from cloudscale.deployment_scripts.scripts.software import deploy_showcase
+
+
+class CreateInstance:
+
+ def __init__(self, config, logger):
+ self.mvn_path = '/usr/bin/mvn'
+ self.cfg = config.cfg
+ self.config = config
+ self.logger = logger
+
+ self.file_path = "/".join(os.path.abspath(__file__).split('/')[:-1])
+ self.remote_user = self.cfg.get('OPENSTACK', 'remote_user')
+ self.key_pair = self.cfg.get('OPENSTACK', 'key_pair')
+ self.remote_deploy_path = self.cfg.get('software', 'remote_deploy_path')
+
+ self.user = self.cfg.get('OPENSTACK', 'username')
+ self.pwd = self.cfg.get('OPENSTACK', 'password')
+ self.url = self.cfg.get('OPENSTACK', 'auth_url')
+ self.tenant = self.cfg.get('OPENSTACK', 'tenant_name')
+ self.db_num_instances = self.cfg.get('MYSQL', 'num_replicas')
+
+ self.image_name = self.cfg.get('OPENSTACK', 'image_name')
+
+ self.instance_type = self.cfg.get('OPENSTACK', 'instance_type')
+ self.instance_name = 'cloudscale-sc'
+
+ self.key_name = self.cfg.get('OPENSTACK', 'key_name')
+ self.key_pair = self.cfg.get('OPENSTACK', 'key_pair')
+
+ self.showcase_image_name = "cloudscale-sc-image"
+
+ self.database_name = self.cfg.get('MYSQL', 'database_name')
+ self.database_user = self.cfg.get('MYSQL', 'database_user')
+ self.database_pass = self.cfg.get('MYSQL', 'database_pass')
+
+ self.connection_pool_size = self.cfg.get('MYSQL', 'connection_pool_size')
+
+ self.database_type = self.cfg.get('OPENSTACK', 'database_type').lower()
+ self.showcase_location = self.cfg.get('MYSQL', 'showcase_war_url')
+ self.deploy_name = "showcase-1-a"
+ if self.database_type != 'mysql':
+ self.deploy_name="showcase-1-b"
+ self.showcase_location = self.cfg.get('MONGODB', 'showcase_war_url')
+ self.showcase_image_name = "cloudscale-sc-mongo-image"
+
+ self.database_name = self.cfg.get('MONGODB', 'database_name')
+ self.database_user = self.cfg.get('MONGODB', 'database_user')
+ self.database_pass = self.cfg.get('MONGODB', 'database_pass')
+
+
+ self.remote_user = self.cfg.get('OPENSTACK', 'image_username')
+
+ self.num_instances = self.config.fr.get('num_instances')
+
+ self.nc = novaclient.Client(self.user, self.pwd, self.tenant, auth_url=self.url)
+ self.delete_image(self.showcase_image_name)
+ self.logger.log("Creating showcase instance image:")
+ images = self.nc.images.list()
+ for image in images:
+ if image.name == self.showcase_image_name:
+ self.logger.log('Image already exists.')
+ break
+ else:
+ self.file_path = os.path.dirname(__file__) + "/../../software"
+
+ userdata = """#!/bin/bash
+USERNAME=%s
+""" % self.remote_user + open(self.file_path + '/install-apache-tomcat.sh', 'r').read()
+ server_id = self.create_instance()
+ time.sleep(40)
+ server_floating_ip = self.add_floating_ip(server_id)
+ self.config.save('infrastructure', 'ip_address', server_floating_ip)
+ self.ip_addresses = self.cfg.get('infrastructure', 'ip_address').split(",")
+ self.add_security_group(server_id, "ssh")
+
+ self.install_software(server_floating_ip, userdata)
+ self.upload_configs(server_floating_ip)
+
+ deploy_showcase.DeploySoftware(self)
+ #self.deploy_showcase(server_floating_ip)
+
+ self.wait_powered_off(server_floating_ip, server_id)
+ self.create_image(server_id, self.showcase_image_name)
+ self.delete_instance(server_id)
+
+ self.logger.log('Done creating showcase instance image')
+
+ self.logger.log('Creating showcase instances')
+ self.create_showcase_instances()
+ self.logger.log('Done creating showcase instances')
+
+ def install_software(self, ip, user_data):
+ self.logger.log('Installing apache and tomcat ...')
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ while True:
+ try:
+ ssh.connect(ip, username=self.remote_user, key_filename=os.path.abspath(self.key_pair))
+ break
+ except:
+ time.sleep(5)
+ time.sleep(30)
+ scp = paramiko.SFTPClient.from_transport(ssh.get_transport())
+ scp.put(self.file_path + '/install-apache-tomcat.sh', 'setup.sh')
+ _, stdout, _ = ssh.exec_command("sh setup.sh")
+ self.wait_for_command(stdout, verbose=True)
+
+ def upload_configs(self, ip):
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ while True:
+ try:
+ ssh.connect(ip, username=self.remote_user, key_filename=os.path.abspath(self.key_pair))
+ break
+ except:
+ time.sleep(5)
+
+ scp = paramiko.SFTPClient.from_transport(ssh.get_transport())
+ self.logger.log("Uploading configs on %s" % ip)
+ scp.put(self.file_path + '/../platform/server.xml', 'server.xml')
+ scp.put(self.file_path + '/cloudscale-apache-virtualhost.conf', 'cloudscale-apache-virtualhost.conf')
+ scp.put(self.file_path + '/../platform/mpm_worker.conf', 'mpm_worker.conf')
+
+ _, stdout, _ = ssh.exec_command("sudo mv server.xml /var/lib/tomcat7/conf/server.xml")
+ self.wait_for_command(stdout, verbose=True)
+
+ _, stdout, _ = ssh.exec_command("sudo mv cloudscale-apache-virtualhost.conf /etc/apache2/sites-available/cloudscale")
+ self.wait_for_command(stdout, verbose=True)
+
+ _, stdout, _ = ssh.exec_command("sudo mv mpm_worker.conf /etc/apache2/mods-enabled/mpm_worker.conf")
+ self.wait_for_command(stdout, verbose=True)
+
+ def wait_for_command(self, stdout, verbose=False):
+ # Wait for the command to terminate
+ while not stdout.channel.exit_status_ready():
+ # Only print data if there is data to read in the channel
+ if stdout.channel.recv_ready():
+ rl, wl, xl = select.select([stdout.channel], [], [], 0.0)
+ if len(rl) > 0:
+ response = stdout.channel.recv(1024)
+ if verbose:
+ print response
+
+ def delete_image(self, image_name):
+ try:
+ for image in self.nc.images.list():
+ if image.name == image_name:
+ image.delete()
+ break
+ except Exception as e:
+ raise e
+
+ def delete_instance(self, server_id):
+ self.logger.log("Deleting instance ...")
+ server = self.nc.servers.get(server_id)
+ server.delete()
+
+ def create_instance(self, image_name=None, files=None, userdata=None, wait_on_active_status=True):
+ if image_name is None:
+ image_name = self.image_name
+
+ flavor = self.nc.flavors.find(name=self.instance_type)
+ if flavor is None:
+ self.logger.log("Instance flavor '%s' not found!" % self.instance_type)
+ return False
+
+ image = self.nc.images.find(name=image_name)
+ if image is None:
+ self.logger.log("Image '%s' not found!" % image_name)
+ return False
+
+ server_id = self.nc.servers.create(
+ self.instance_name, image, flavor, key_name=self.key_name, files=files, userdata=userdata
+ ).id
+
+ #if wait_on_active_status and not self.wait_active(server_id):
+ # return False
+
+ return server_id
+
+ def wait_active(self, server_id):
+ self.logger.log("Waiting for instance to be built . . .")
+ status = self.wait_for_instance_status(server_id, u'BUILD', u'ACTIVE')
+ if not status:
+ self.logger.log("Can not start instance %s!" % self.instance_name)
+ return False
+ return True
+
+ def wait_all_instances_active(self, instance_ids):
+ for instance_id in instance_ids:
+ self.wait_active(instance_id)
+
+ def wait_powered_off(self, ip, server_id):
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ ssh.connect(ip, username=self.remote_user, key_filename=os.path.abspath(self.key_pair))
+ _, stdout, _ = ssh.exec_command("sudo poweroff")
+ self.wait_for_command(stdout, verbose=True)
+
+ self.logger.log("Waiting for instance %s to be powered off . . ." % server_id)
+ status = self.wait_for_instance_status(server_id, u'ACTIVE', u'SHUTOFF')
+ if not status:
+ self.logger.log("Error on instance %s!" % self.instance_name)
+ return False
+ return True
+
+ def wait_for_instance_status(self, server_id, current_status, wait_for_status):
+ while True:
+ server = self.nc.servers.get(server_id)
+ if server.status != current_status:
+ if server.status == wait_for_status:
+ return True
+ return False
+ time.sleep(1)
+
+ def create_image(self, server_id, image_name):
+ self.logger.log("Creating image ...")
+ server = self.nc.servers.get(server_id)
+ image_id = server.create_image(image_name)
+
+ while True:
+ image = self.nc.images.get(image_id)
+ if image.status == u'ACTIVE':
+ return True
+ if image.status == u'ERROR':
+ self.logger.log("Error creating image!")
+ return False
+ time.sleep(10)
+
+ def compile(self):
+ self.logger.log("Downloading showcase from Jenkins...")
+ if self.database_type == "mysql":
+ ps = subprocess.Popen('cd ' + self.file_path + '/showcase; '+ self.mvn_path + ' -Pamazon-hibernate -Dconnection_pool_size='
+ + self.connection_pool_size + ' install',
+ shell=True)
+ ps.wait()
+ if ps.returncode != 0:
+ self.logger.log("ERROR: showcase failed to compile!")
+ pass
+ else:
+ ps = subprocess.Popen('cd ' + self.file_path + '/showcase; ' + self.mvn_path + ' -Pamazon-mongodb -Dconnection_pool_size='
+ + self.connection_pool_size + ' install',
+ shell=True)
+ ps.wait()
+ if ps.returncode != 0:
+ self.logger.log("ERROR: showcase failed to compile!")
+ pass
+
+ def create_showcase_instances(self):
+ showcase_server_ids = []
+
+ for i in range(int(self.num_instances)):
+ self.logger.log("Creating showcase instance %s ..." % (i + 1))
+ showcase_server_ids.append(
+ self.create_instance(image_name=self.showcase_image_name, wait_on_active_status=False)
+ )
+ time.sleep(60)
+
+ self.wait_all_instances_active(showcase_server_ids)
+
+ for server_id in showcase_server_ids:
+ self.add_security_group(server_id, 'http')
+
+ def add_floating_ip(self, server_id):
+ server = self.nc.servers.get(server_id)
+ unallocated_floating_ips = self.nc.floating_ips.findall(fixed_ip=None)
+ if len(unallocated_floating_ips) < 1:
+ unallocated_floating_ips.append(self.nc.floating_ips.create())
+ floating_ip = unallocated_floating_ips[0]
+ server.add_floating_ip(floating_ip)
+ return floating_ip.ip
+
+ def add_security_group(self, server_id, group_name):
+ self.logger.log("Adding security group %s" % group_name)
+ server = self.nc.servers.get(server_id)
+ server.add_security_group(group_name)
+
+ def deploy_showcase(self, ip_address):
+ self.logger.log("Connecting to ssh on %s" % ip_address)
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ while True:
+ try:
+ ssh.connect(ip_address, username=self.remote_user, key_filename=os.path.abspath(self.key_pair))
+ break
+ except:
+ time.sleep(5)
+
+ scp = paramiko.SFTPClient.from_transport(ssh.get_transport())
+ self.logger.log("Uploading showcase.war")
+ ssh.exec_command('wget')
+ scp.put(self.file_path + '/showcase/target/showcase-1.0.0-BUILD-SNAPSHOT.war', 'showcase-1-a.war')
+ _, stdout, _ = ssh.exec_command("sudo mv showcase-1-a.war /var/lib/tomcat7/webapps")
+ self.wait_for_command(stdout, verbose=True)
+ ssh.exec_command("sudo chown tomcat7:tomcat7 /var/lib/tomcat7/webapps/showcase-1-a.war")
+
+ def get_ip(self, server):
+ for address in server.addresses[server.addresses.keys()[0]]:
+ if address['OS-EXT-IPS:type'] == 'fixed':
+ server_ip = address['addr']
+ break
+ else:
+ server_ip = None
+ self.logger.log("Error: can not get IP address of this server")
+ return server_ip
+
+ def create_showcase_database_config(self):
+ if self.database_type == 'mysql':
+ self.logger.log("Creating jdbc configuration")
+ path = self.file_path + '/showcase/src/main/resources/database/database.aws.hibernate.properties'
+
+ master_server = self.nc.servers.findall(name='cloudscale-db-master')
+ servers = self.nc.servers.findall(name='cloudscale-db')
+ ips = [self.get_ip(master_server[0])]
+ for server in servers:
+ server_ip = self.get_ip(server)
+ ips.append(server_ip)
+ urls = ','.join(ips)
+
+ f = open(path, 'w')
+ f.write('jdbc.dbtype=mysql\n')
+ driver = 'jdbc.driverClassName=com.mysql.jdbc.Driver\n'
+ jdbc_url = 'jdbc.url=jdbc:mysql:loadbalance://%s/%s?autoReconnect=true&loadBalanceBlacklistTimeout=5000\n' % (urls, self.database_name)
+ if self.config.db.get('setup_type') == 'master-slave':
+ driver = 'jdbc.driverClassName=com.mysql.jdbc.ReplicationDriver\n'
+ jdbc_url = 'jdbc.url=jdbc:mysql:replication://%s/%s?autoReconnect=true\n' % (urls, self.database_name)
+
+ f.write(driver)
+ f.write(jdbc_url)
+ f.write('jdbc.username=%s\n' % self.database_user)
+ f.write('jdbc.password=%s\n' % self.database_pass)
+ f.write('jdbc.hibernate.dialect=org.hibernate.dialect.MySQLDialect\n')
+ f.close()
+ else:
+ self.logger.log("Creating jdbc configuration")
+ path = self.file_path + '/showcase/src/main/resources/database/database.aws.mongodb.properties'
+
+ servers = self.nc.servers.findall(name='cloudscale-db-mongo')
+ ips = []
+ for server in servers:
+ server_ip = self.get_ip(server)
+ ips.append(server_ip)
+ urls = ','.join(ips)
+
+ f = open(path, 'w')
+ f.write('jdbc.dbtype=mongodb\n')
+ f.write('mongodb.dbname=tpcw\n')
+ f.write('mongodb.host=%s\n' % ips[0])
+ f.write('mongodb.port=27017\n')
+ f.write('mongodb.username=tpcw\n')
+ f.write('mongodb.password=Yhm.3Ub+\n')
+ f.close()
+
+
+if __name__ == '__main__':
+ check_args(2, "<output_dir> <config_path>")
+ path, cfg, logger = get_cfg_logger(sys.argv[1], sys.argv[2])
+ CreateInstance(cfg, logger)
diff --git a/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_remove_all.py b/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_remove_all.py
new file mode 100644
index 0000000..ed91150
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack_remove_all.py
@@ -0,0 +1,132 @@
+import os
+from novaclient.exceptions import NotFound, BadRequest, NoUniqueMatch
+import time
+
+from novaclient.v2 import client as novaclient
+import sys
+from cloudscale.deployment_scripts.scripts import check_args, get_cfg_logger
+
+
+class RemoveAll:
+ def __init__(self, config, logger):
+ self.cfg = config.cfg
+ self.config = config
+ self.logger = logger
+
+ self.user = self.cfg.get('OPENSTACK', 'username')
+ self.pwd = self.cfg.get('OPENSTACK', 'password')
+ self.url = self.cfg.get('OPENSTACK', 'auth_url')
+ self.tenant = self.cfg.get('OPENSTACK', 'tenant_name')
+
+ self.image_name = self.cfg.get('OPENSTACK', 'image_name')
+ self.instance_type = self.cfg.get('OPENSTACK', 'instance_type')
+ self.instance_name = 'cloudscale'
+ self.key_name = self.cfg.get('OPENSTACK', 'key_name')
+ self.key_pair = self.cfg.get('OPENSTACK', 'key_pair')
+
+ self.nc = novaclient.Client(self.user, self.pwd, self.tenant, auth_url=self.url)
+
+ self.logger.log("Cleaning:")
+ self.remove_openstack_instances()
+ # TODO: remove images
+ self.remove_key_pair()
+ self.remove_security_groups()
+ self.logger.log("Done cleaning")
+
+ self.logger.log('Creating security groups and key-pair:')
+ self.create_security_groups()
+ self.create_key_pair()
+ self.logger.log('Done creating security groups and key-pair')
+
+ def remove_key_pair(self):
+ self.logger.log("Removing key pair ...")
+ try:
+ self.nc.keypairs.find(name=self.key_name).delete()
+ except NotFound as e:
+ pass
+
+ def remove_openstack_instances(self):
+ self.logger.log("Terminating openstack instances ...")
+
+ instance_ids = []
+ for server in self.nc.servers.list():
+ if server.name in ('cloudscale-db', 'cloudscale-db-master', 'cloudscale-sc', 'cloudscale-lb', 'cloudscale-mc'):
+ instance_ids.append(server.id)
+ server.delete()
+ time.sleep(10)
+
+ for instance_id in instance_ids:
+ self.wait_terminate(instance_id)
+
+ def wait_terminate(self, instance_id):
+ self.logger.log("Waiting for instance to terminate, please wait ...")
+ while True:
+ try:
+ server = self.nc.servers.get(instance_id)
+ except NotFound as e:
+ break
+ time.sleep(3)
+ self.logger.log("Instance is terminated!")
+
+ def remove_security_groups(self):
+ self.logger.log("Removing security groups ...")
+
+ groups = ['ssh', 'http', 'galera', 'mongodb', 'web-deploy']
+ for group in groups:
+ try:
+ self.nc.security_groups.find(name=group).delete()
+ except (NoUniqueMatch, NotFound, BadRequest):
+ pass
+ except Exception as exc:
+ pass
+
+ def create_key_pair(self):
+ self.logger.log("Creating key pair ...")
+ if os.path.isfile(self.key_pair):
+ if not os.path.isfile(self.key_pair + '.pub'):
+ self.logger.log("Can not find public key %s!" % (self.key_pair + '.pub'))
+ exit(1)
+ public_key = open(self.key_pair + '.pub', 'r').read()
+ self.nc.keypairs.create(self.key_name, public_key=public_key)
+ else:
+ try:
+ keypair = self.nc.keypairs.find(name=self.key_name)
+ except NotFound as e:
+ keypair = self.nc.keypairs.create(self.key_name)
+
+ open(self.key_pair + '.pub', 'w').write(keypair.public_key)
+ open(self.key_pair, 'w').write(keypair.private_key)
+
+ def create_security_groups(self):
+ self.logger.log("Creating security groups http and ssh ...")
+ self.create_security_group('http', 'Security group for HTTP protocol', 'tcp', '80', '0.0.0.0/0')
+ self.create_security_group('ssh', 'Security group for SSH protocol', 'tcp', '22', '0.0.0.0/0')
+ self.create_security_group('galera', 'Security group for MySQL galera protocol', 'tcp',
+ ['3306', '4444', '4567', '4568'], '0.0.0.0/0')
+ self.create_security_group('mongo', 'Security group for MongoDB protocol', 'tcp',
+ ['27017', '27037', '27019'], '0.0.0.0/0')
+
+ def create_security_group(self, name, description, protocol, ports, cidr):
+ try:
+ security_group = self.nc.security_groups.find(name=name)
+ except NotFound:
+ security_group = self.nc.security_groups.create(name, description)
+ except Exception as e:
+ raise e
+
+ try:
+ if not isinstance(ports, list):
+ ports = [ports]
+ for port in ports:
+ self.nc.security_group_rules.create(security_group.id, protocol, port, port, cidr)
+ except BadRequest as e:
+ if e.message != u'Security group %s already exists' % name and e.message != u'This rule already exists in group %s' % security_group.id:
+ raise
+ except Exception as e:
+ pass
+
+if __name__ == "__main__":
+ check_args(2, "<output_dir> <config_path>")
+ path, cfg, logger = get_cfg_logger(sys.argv[1], sys.argv[2])
+
+ RemoveAll(cfg, logger)
diff --git a/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack-create-instance.py b/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack-create-instance.py
new file mode 100644
index 0000000..8260b90
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/infrastructure/openstack/openstack-create-instance.py
@@ -0,0 +1,30 @@
+from novaclient.v2 import client as novaclient
+import sys
+from cloudscale.deployment_scripts.scripts import check_args, get_cfg_logger
+
+
+class CreateInstance:
+
+ def __init__(self, cfg):
+ self.cfg = cfg
+ self.user = cfg.get('OPENSTACK', 'username')
+ self.pwd = cfg.get('OPENSTACK', 'password')
+ self.url = cfg.get('OPENSTACK', 'auth_url')
+ self.tenant = cfg.get('OPENSTACK', 'tenant_name')
+ self.image_name = cfg.get('OPENSTACK', 'image_name')
+ server = self.create_instance()
+ print [s['addr'] for s in server.addresses[self.tenant] if s['OS-EXT-IPS:type'] == 'floating'][0]
+
+ def create_instance(self):
+ nc = novaclient.Client(self.user, self.pwd, self.tenant, auth_url=self.url)
+ for f in nc.flavors.list():
+ print f
+ # nc.servers.create('cloudscale', self.image_name, )
+ for server in nc.servers.list():
+ if server._info['name'] == self.instance_name:
+ return server
+
+if __name__ == '__main__':
+ check_args(2, "<output_dir> <config_path>")
+ path, cfg, logger = get_cfg_logger(sys.argv[1], sys.argv[2])
+ CreateInstance(cfg)
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/__init__.py b/cloudscale/deployment_scripts/scripts/platform/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/__init__.py
diff --git a/cloudscale/deployment_scripts/scripts/platform/aws/__init__.py b/cloudscale/deployment_scripts/scripts/platform/aws/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/aws/__init__.py
diff --git a/cloudscale/deployment_scripts/scripts/platform/aws/configure_rds.py b/cloudscale/deployment_scripts/scripts/platform/aws/configure_rds.py
new file mode 100644
index 0000000..72dd94a
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/aws/configure_rds.py
@@ -0,0 +1,185 @@
+import boto.exception
+import boto, boto.ec2, boto.rds
+import boto.manage.cmdshell
+import time
+import subprocess
+import os
+import sys
+from cloudscale.deployment_scripts.scripts import check_args, get_cfg_logger
+
+
+class ConfigureRDS:
+
+ def __init__(self, config, logger):
+ self.cfg = config.cfg
+ self.config = config
+ self.logger=logger
+ self.db_password= self.cfg.get('RDS', 'database_pass')
+
+ self.conn = boto.rds.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+ sg_id = self.create_security_group('mysql', 'Security group for MYSQL protocol', '3306', '0.0.0.0/0')
+ instance = self.create_master(sg_id)
+ self.import_data(instance)
+
+ replicas_urls = []
+ if int(self.cfg.get('RDS', 'num_replicas')) > 0:
+ replicas_urls = self.create_read_replicas()
+
+ self.write_config(instance.endpoint[0], replicas_urls)
+
+ def create_read_replicas(self):
+ num = int(self.cfg.get('RDS', 'num_replicas'))
+ urls = []
+ instance_ids = []
+ for i in xrange(int(num)):
+ self.logger.log("Creating read replica " + str(i+1))
+ try:
+ instance = self.conn.create_dbinstance_read_replica(
+ self.cfg.get('RDS', 'replica_identifier') + str(i+1),
+ self.cfg.get('RDS', 'master_identifier'),
+ self.cfg.get('RDS', 'instance_type'),
+ availability_zone="eu-west-1a"
+ )
+ except boto.exception.BotoServerError as e:
+ if not e.error_code == 'DBInstanceAlreadyExists':
+ raise
+ else:
+ id = self.cfg.get('RDS', 'replica_identifier') + str(i+1)
+ self.logger.log("Modifying RDS %s" % id)
+ self.conn.modify_dbinstance(id=id, instance_class=self.cfg.get('RDS', 'instance_type'), apply_immediately=True)
+ time.sleep(60)
+
+ for i in xrange(int(num)):
+ instance = self.conn.get_all_dbinstances(instance_id=self.cfg.get('RDS', 'replica_identifier') + str(i+1))[0]
+ self.wait_available(instance)
+ instance = self.conn.get_all_dbinstances(instance_id=self.cfg.get('RDS', 'replica_identifier')+ str(i+1))[0]
+ urls.append(instance.endpoint[0])
+
+ return urls
+
+
+ def import_data(self, instance):
+ self.logger.log("Importing data. This may take a while, please wait ...")
+ generate_type = self.cfg.get('RDS', 'generate_type')
+
+ if generate_type == "script":
+ config_path = self.write_showcase_database_config(instance)
+ self.generate(config_path)
+ elif generate_type == "dump":
+ self.dump(instance)
+
+ self.logger.log("Successfully imported data")
+
+ def dump(self, instance):
+ dump_file = self.cfg.get('RDS', 'generate_dump_path')
+ db = self.cfg.get('RDS', 'database_name')
+ user = self.cfg.get('RDS', 'database_user')
+ passwd = self.cfg.get('RDS', 'database_pass')
+ cmd = [os.path.dirname(__file__) + "/dump.sh", str(instance.endpoint[0]), user, passwd, db, dump_file]
+ subprocess.check_output(cmd)
+
+ def write_showcase_database_config(self, instance):
+ path = os.path.abspath('../generator/src/main/resources/generate/database.properties')
+ self.logger.log(path)
+ f = open(path, 'w')
+ f.write("jdbc.dbtype=mysql\n")
+ f.write("jdbc.driverClassName=com.mysql.jdbc.Driver\n")
+ f.write("jdbc.url=jdbc:mysql://" + instance.ip_address + "/tpcw\n")
+ f.write("jdbc.username=root\n")
+ f.write("jdbc.password=" + self.db_password + "\n")
+ f.write("jdbc.hibernate.dialect=org.hibernate.dialect.MySQLDialect\n")
+ f.close()
+ return path
+
+ def generate(self, config_path):
+ script_path = os.path.abspath('generate.sh')
+ subprocess.call([script_path, 'file:///' + config_path, self.cfg.get('RDS', 'generate_type')])
+
+
+ def write_config(self, instance):
+ f = open('../database.properties', 'w')
+ f.write('')
+
+ def create_security_group(self, name, description, port, cidr):
+ ec2_conn = boto.ec2.connect_to_region(self.cfg.get('EC2', 'region'),
+ aws_access_key_id=self.cfg.get('EC2', 'aws_access_key_id'),
+ aws_secret_access_key=self.cfg.get('EC2', 'aws_secret_access_key'))
+ try:
+ ec2_conn.create_security_group(name, description)
+ ec2_conn.authorize_security_group(group_name=name, ip_protocol='tcp', from_port=port, to_port=port, cidr_ip=cidr)
+
+ self.conn.create_dbsecurity_group(name, description)
+ self.conn.authorize_dbsecurity_group(name, cidr, name)
+ except boto.exception.EC2ResponseError as e:
+ if str(e.error_code) != 'InvalidGroup.Duplicate':
+ raise e
+ finally:
+ return ec2_conn.get_all_security_groups(groupnames=['mysql'])[0].id
+
+ def create_master(self, sg_id):
+
+ self.logger.log("Creating RDS master instance ...")
+
+ try:
+ instance = self.conn.create_dbinstance(
+ self.cfg.get('RDS', 'master_identifier'),
+ 5,
+ self.cfg.get('RDS', 'instance_type'),
+ self.cfg.get('RDS', 'database_user'),
+ self.cfg.get('RDS', 'database_pass'),
+ db_name=self.cfg.get('RDS', 'database_name'),
+ vpc_security_groups=[sg_id],
+ availability_zone='eu-west-1a',
+ backup_retention_period=1
+ )
+ except boto.exception.BotoServerError as e:
+ if not e.error_code == 'DBInstanceAlreadyExists':
+ raise Exception(e)
+ else:
+ id = self.cfg.get('RDS', 'master_identifier')
+ self.logger.log("Modifying RDS %s ..." % id)
+ self.conn.modify_dbinstance(id=id, instance_class=self.cfg.get('RDS', 'instance_type'), apply_immediately=True)
+ #time.sleep(60)
+ finally:
+ instance = self.conn.get_all_dbinstances(instance_id=self.cfg.get('RDS', 'master_identifier'))[0]
+
+ self.wait_available(instance)
+
+ instance = self.conn.get_all_dbinstances(instance_id=self.cfg.get('RDS', 'master_identifier'))[0]
+
+ return instance
+
+
+ def wait_available(self, instance):
+ self.logger.log("Waiting for instance to become available\nPlease wait . .")
+ status = self.conn.get_all_dbinstances(instance.id)[0].status
+ i=1
+ while status != 'available':
+ if i%10 == 0:
+ self.logger.log("\nPlease wait .")
+ self.logger.log('.', append_to_last=True)
+ status = self.conn.get_all_dbinstances(instance.id)[0].status
+ time.sleep(3)
+ i=i+1
+
+ time.sleep(5)
+
+ self.logger.log("Instance is running!")
+
+ def write_config(self, master_url, replica_urls=[]):
+ urls = master_url
+ if len(replica_urls) > 0:
+ urls += "," + ",".join(replica_urls)
+ self.config.save('platform', 'urls', urls)
+ # f = open(os.path.abspath('../platform.ini'), 'w')
+ # f.write('[Database]\n')
+ # f.write('db_urls=' + master_url)
+ # for url in replica_urls:
+ # f.write(',' + url)
+
+if __name__ == "__main__":
+ check_args(2, "<output_dir> <config_path>")
+ path, cfg, logger = get_cfg_logger(sys.argv[1], sys.argv[2])
+ ConfigureRDS(cfg, logger)
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/aws/configure-dynamodb.py b/cloudscale/deployment_scripts/scripts/platform/aws/configure-dynamodb.py
new file mode 100644
index 0000000..8f76346
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/aws/configure-dynamodb.py
@@ -0,0 +1 @@
+__author__ = 'ivansek'
diff --git a/cloudscale/deployment_scripts/scripts/platform/aws/dump.sh b/cloudscale/deployment_scripts/scripts/platform/aws/dump.sh
new file mode 100755
index 0000000..2b08049
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/aws/dump.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+PATH_TO_MYSQL_COMMAND=/usr/bin
+
+if [ $# -lt 5 ]
+then
+ echo -e "Usage:\n$ dump.sh <host> <user> <password> <database> <dump_file_path>"
+ exit
+fi
+
+${PATH_TO_MYSQL_COMMAND}/mysql -h $1 -u $2 -p$3 --database=$4 < $5
diff --git a/cloudscale/deployment_scripts/scripts/platform/aws/generate.sh b/cloudscale/deployment_scripts/scripts/platform/aws/generate.sh
new file mode 100755
index 0000000..ae69adb
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/aws/generate.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+PATH_TO_MVN_COMMAND=/usr/local/bin
+
+if [ $# -lt 1 ]
+then
+ echo -e "Usage:\n$ generate.sh <path_to_config_file>"
+ exit
+fi
+
+if [ $2 == "dump" ]
+then
+ mysql -h
+cd ../generator/
+${PATH_TO_MVN_COMMAND}/mvn -Pamazon-hibernate -Deu.cloudscale.showcase.generate.properties=$1 install
+java -cp target/dependency/*:target/showcase-1.0.0-BUILD-SNAPSHOT.jar eu.cloudscale.showcase.generate.Generate mysql
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/pom.xml b/cloudscale/deployment_scripts/scripts/platform/generator/pom.xml
new file mode 100644
index 0000000..8cf25d4
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/pom.xml
@@ -0,0 +1,406 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>eu.cloudscale</groupId>
+ <artifactId>showcase</artifactId>
+ <name>40-Spring_webshop</name>
+ <packaging>jar</packaging>
+ <version>1.0.0-BUILD-SNAPSHOT</version>
+ <repositories>
+ <repository>
+ <id>spring-milestone</id>
+ <name>Spring Maven MILESTONE Repository</name>
+ <url>http://repo.springsource.org/libs-milestone</url>
+ </repository>
+ </repositories>
+ <properties>
+ <org.springframework.version>3.2.1.RELEASE</org.springframework.version>
+ <log4j.version>1.2.17</log4j.version>
+ </properties>
+ <dependencies>
+ <!-- Spring -->
+
+ <!-- Logging -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>1.7.5</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.7.5</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.7.5</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>${log4j.version}</version>
+ </dependency>
+
+ <!-- <dependency> -->
+ <!-- <groupId>javax.inject</groupId> -->
+ <!-- <artifactId>javax.inject</artifactId> -->
+ <!-- <version>1</version> -->
+ <!-- </dependency> -->
+
+ <!-- Servlet -->
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet.jsp</groupId>
+ <artifactId>jsp-api</artifactId>
+ <version>2.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>jstl</artifactId>
+ <version>1.2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.data</groupId>
+ <artifactId>spring-data-mongodb</artifactId>
+ <version>1.2.0.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.thymeleaf</groupId>
+ <artifactId>thymeleaf-spring3</artifactId>
+ <version>2.0.16</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-orm</artifactId>
+ <version>${org.springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <version>${org.springframework.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ <version>${org.springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>${org.springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>${org.springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ <version>4.1.9.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-dbcp</groupId>
+ <artifactId>commons-dbcp</artifactId>
+ <version>1.2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>com.mchange</groupId>
+ <artifactId>c3p0</artifactId>
+ <version>0.9.5-pre1</version>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <version>5.1.24</version>
+ </dependency>
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib</artifactId>
+ <version>3.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-c3p0</artifactId>
+ <version>4.1.9.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-ehcache</artifactId>
+ <version>4.1.9.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>net.sf.ehcache</groupId>
+ <artifactId>ehcache</artifactId>
+ <version>2.7.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>${org.springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context-support</artifactId>
+ <version>${org.springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate</artifactId>
+ <version>3.6.0.Beta2</version>
+ <type>pom</type>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-jdbc</artifactId>
+ <version>${org.springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>nz.net.ultraq.thymeleaf</groupId>
+ <artifactId>thymeleaf-layout-dialect</artifactId>
+ <version>1.1.3</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <configuration>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+ <!-- <plugin> -->
+ <!-- <groupId>org.codehaus.cargo</groupId> -->
+ <!-- <artifactId>cargo-maven2-plugin</artifactId> -->
+ <!-- <version>1.3.3</version> -->
+ <!-- <configuration> -->
+ <!-- <container> -->
+ <!-- <containerId>tomcat7x</containerId> -->
+ <!-- <type>remote</type> -->
+
+ <!-- </container> -->
+ <!-- <configuration> -->
+ <!-- <timeout>60000</timeout> -->
+ <!-- <type>runtime</type> -->
+ <!-- <properties> -->
+ <!-- <cargo.hostname>10.10.40.23</cargo.hostname> -->
+ <!-- <cargo.servlet.port>8081</cargo.servlet.port> -->
+ <!-- <cargo.remote.uri>http://10.10.40.23:8081/manager/text</cargo.remote.uri> -->
+ <!-- <cargo.remote.username>remote-deploy</cargo.remote.username> -->
+ <!-- <cargo.remote.password>prfct42x</cargo.remote.password> -->
+ <!-- </properties> -->
+ <!-- </configuration> -->
+ <!-- <deployer> -->
+ <!-- <type>remote</type> -->
+ <!-- </deployer> -->
+ <!-- <deployables> -->
+ <!-- <deployable> -->
+ <!-- <groupId>${project.groupId}</groupId> -->
+ <!-- <artifactId>${project.artifactId}</artifactId> -->
+ <!-- <type>war</type> -->
+ <!-- <properties> -->
+ <!-- <context>${project.artifactId}</context> -->
+ <!-- </properties> -->
+ <!-- <pingURL>http://10.10.40.23:8081/showcase-1</pingURL> -->
+ <!-- </deployable> -->
+ <!-- </deployables> -->
+ <!-- </configuration> -->
+ <!-- </plugin> -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>2.4</version>
+ <!-- Enable filtering in web.xml -->
+ <configuration>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ </manifest>
+ </archive>
+ <webResources>
+ <resource>
+ <filtering>true</filtering>
+ <directory>src/main/webapp</directory>
+ <includes>
+ <include>**/web.xml</include>
+ </includes>
+ </resource>
+ </webResources>
+ <warSourceDirectory>src/main/webapp</warSourceDirectory>
+ <webXml>src/main/webapp/WEB-INF/web.xml</webXml>
+ </configuration>
+ </plugin>
+ <!-- <plugin> -->
+ <!-- <artifactId>maven-eclipse-plugin</artifactId> -->
+ <!-- <version>2.9</version> -->
+ <!-- <configuration> -->
+ <!-- <additionalProjectnatures> -->
+ <!-- <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature> -->
+ <!-- </additionalProjectnatures> -->
+ <!-- <additionalBuildcommands> -->
+ <!-- <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand> -->
+ <!-- </additionalBuildcommands> -->
+ <!-- <downloadSources>true</downloadSources> -->
+ <!-- <downloadJavadocs>true</downloadJavadocs> -->
+ <!-- </configuration> -->
+ <!-- </plugin> -->
+ <!-- <plugin> -->
+ <!-- <groupId>org.apache.maven.plugins</groupId> -->
+ <!-- <artifactId>maven-compiler-plugin</artifactId> -->
+ <!-- <version>2.5.1</version> -->
+ <!-- <configuration> -->
+ <!-- <source>1.6</source> -->
+ <!-- <target>1.6</target> -->
+ <!-- <compilerArgument>-Xlint:all</compilerArgument> -->
+ <!-- <showWarnings>true</showWarnings> -->
+ <!-- <showDeprecation>true</showDeprecation> -->
+ <!-- </configuration> -->
+ <!-- </plugin> -->
+ <!-- <plugin> -->
+ <!-- <groupId>org.codehaus.mojo</groupId> -->
+ <!-- <artifactId>exec-maven-plugin</artifactId> -->
+ <!-- <configuration> -->
+ <!-- <mainClass>org.test.int1.Main</mainClass> -->
+ <!-- </configuration> -->
+ <!-- </plugin> -->
+ <!-- <plugin> -->
+ <!-- <artifactId>maven-assembly-plugin</artifactId> -->
+ <!-- <configuration> -->
+ <!-- <archive> -->
+ <!-- <manifest> -->
+ <!-- <mainClass>eu.cloudscaleproject.showcase.db.generate.Generate</mainClass> -->
+ <!-- </manifest> -->
+ <!-- </archive> -->
+ <!-- <descriptorRefs> -->
+ <!-- <descriptorRef>jar-with-dependencies</descriptorRef> -->
+ <!-- </descriptorRefs> -->
+ <!-- </configuration> -->
+ <!-- <executions> -->
+ <!-- <execution> -->
+ <!-- <id>make-assembly</id> -->
+ <!-- <phase>package</phase> -->
+ <!-- <goals> -->
+ <!-- <goal>single</goal> -->
+ <!-- </goals> -->
+ <!-- </execution> -->
+ <!-- </executions> -->
+ <!-- </plugin> -->
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.2.1</version>
+ <configuration>
+ <executable>java</executable>
+ <arguments>
+ <argument>-Djava.library.path=${project.build.directory}/lib</argument>
+ <argument>-classpath ${compile.classpath}</argument>
+ <argument>eu.cloudscale.showcase.generate.Generate</argument>
+ <argument>${dbtype}</argument>
+ </arguments>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.8</version>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>false</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ <excludes>
+ <exclude>jmeter</exclude>
+ <exclude>matlab</exclude>
+ <exclude>rbe</exclude>
+ <exclude>results</exclude>
+ <exclude>aws</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>
+ org.apache.maven.plugins
+ </groupId>
+ <artifactId>
+ maven-dependency-plugin
+ </artifactId>
+ <versionRange>
+ [2.8,)
+ </versionRange>
+ <goals>
+ <goal>
+ copy-dependencies
+ </goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ <profiles>
+ <profile>
+ <id>amazon-hibernate</id>
+ <properties>
+ <eu.cloudscale.environment>aws</eu.cloudscale.environment>
+ <eu.cloudscale.datasource>hibernate</eu.cloudscale.datasource>
+ <eu.cloudscale.showcase.generate.properties>database/database.aws.hibernate.properties</eu.cloudscale.showcase.generate.properties>
+ </properties>
+ </profile>
+ <profile>
+ <id>amazon-mongodb</id>
+ <properties>
+ <eu.cloudscale.environment>aws</eu.cloudscale.environment>
+ <eu.cloudscale.datasource>mongodb</eu.cloudscale.datasource>
+ </properties>
+ </profile>
+ </profiles>
+</project>
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/AService.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/AService.java
new file mode 100644
index 0000000..8be2422
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/AService.java
@@ -0,0 +1,419 @@
+package eu.cloudscale.showcase.db;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.transaction.annotation.Transactional;
+
+import eu.cloudscale.showcase.db.dao.IAddressDao;
+import eu.cloudscale.showcase.db.dao.IAuthorDao;
+import eu.cloudscale.showcase.db.dao.ICcXactsDao;
+import eu.cloudscale.showcase.db.dao.ICountryDao;
+import eu.cloudscale.showcase.db.dao.ICustomerDao;
+import eu.cloudscale.showcase.db.dao.IItemDao;
+import eu.cloudscale.showcase.db.dao.IOrderLineDao;
+import eu.cloudscale.showcase.db.dao.IOrdersDao;
+import eu.cloudscale.showcase.db.dao.IShoppingCartDao;
+import eu.cloudscale.showcase.db.dao.IShoppingCartLineDao;
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.IAuthor;
+import eu.cloudscale.showcase.db.model.ICcXacts;
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.model.IItem;
+import eu.cloudscale.showcase.db.model.IOrderLine;
+import eu.cloudscale.showcase.db.model.IOrders;
+import eu.cloudscale.showcase.db.model.IShoppingCart;
+import eu.cloudscale.showcase.db.model.IShoppingCartLine;
+
+@Transactional(readOnly=true)
+public abstract class AService implements IService
+{
+ @SuppressWarnings( "rawtypes" )
+ @Override
+ @Cacheable("newProducts")
+ public List getNewProducts(String category)
+ {
+ return getItemDaoImpl().getNewProducts( category );
+ }
+
+ @Override
+ @Transactional(readOnly=false)
+ public IShoppingCart doCart(Integer shoppingId, Integer itemId,
+ List<Integer> ids, List<Integer> quantities)
+ {
+
+ IShoppingCartLineDao sclDao = getShoppingCartLineDaoImpl();
+ IShoppingCartDao scDao = getShoppingCartDaoImpl();
+ IItemDao itemDao = getItemDaoImpl();
+
+ if ( itemId != null )
+ {
+ addItem( shoppingId, itemDao.findById( itemId.intValue() ) );
+ }
+
+ refreshCart( shoppingId, ids, quantities );
+ addRandomItemToCartIfNecessary( sclDao, shoppingId );
+ resetCartTime( sclDao, shoppingId );
+
+ return scDao.findById( shoppingId );
+ }
+
+ @Transactional(readOnly=false)
+ protected void addRandomItemToCartIfNecessary(IShoppingCartLineDao sclDao,
+ int SHOPPING_ID)
+ {
+ // check and see if the cart is empty. If it's not, we do
+ // nothing.
+
+ try
+ {
+ // Check to see if the cart is empty
+ if ( sclDao.isCartEmpty( SHOPPING_ID ) )
+ {
+ // Cart is empty
+ addItem( SHOPPING_ID, getItemDaoImpl().getRandomItem() );
+ }
+
+ }
+ catch ( java.lang.Exception ex )
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ protected IShoppingCart getCart(Integer shoppingId, double discount)
+ {
+ IShoppingCartDao scDao = getShoppingCartDaoImpl();
+ IShoppingCart sc = scDao.findById( shoppingId );
+ return sc;
+ }
+
+ @Transactional(readOnly=false)
+ protected void resetCartTime(IShoppingCartLineDao sclDao, Integer shoppingId)
+ {
+ IShoppingCartDao scDao = getShoppingCartDaoImpl();
+ IShoppingCart sc = scDao.findById( shoppingId );
+ sc.setScTime( new Date() );
+ scDao.shrani( sc );
+ }
+
+ // protected void addRandomItemToCartIfNecessary(
+ // IShoppingCartLineDao sclDao, Integer shoppingId)
+ // {
+ // IItemDao itemDao = getItemDaoImpl();
+ //
+ // if ( sclDao.isCartEmpty( shoppingId ) )
+ // {
+ // IItem randItem = itemDao.getRandomItem();
+ // // related_item = getRelated1(sclDao, shoppingId, randItem);
+ // addItem( shoppingId, randItem );
+ // }
+ //
+ // }
+
+ // protected IItem getRelated1(IShoppingCartLineDao<IShoppingCartLine>
+ // sclDao,
+ // Integer shoppingId,
+ // IItem randItem)
+ // {
+ // IItemDao<IItem> itemDao = getItemDaoImpl();
+ // IItem relatedItem = itemDao.getRelated1( randItem );
+ // return relatedItem;
+ // }
+
+ @Transactional(readOnly=false)
+ protected void refreshCart(Integer shoppingId, List<Integer> ids,
+ List<Integer> quantities)
+ {
+ IShoppingCartLineDao sclDao = getShoppingCartLineDaoImpl();
+ for ( int i = 0; i < ids.size(); i++ )
+ {
+ int itemId = ids.get( i );
+ int QTY = quantities.get( i );
+ IShoppingCartLine scl = sclDao.getBySCandItem( shoppingId, itemId );
+ if ( QTY == 0 )
+ {
+ sclDao.delete( scl );
+ }
+ else
+ {
+ scl.setSclQty( QTY );
+ sclDao.shrani( scl );
+ }
+ }
+
+ }
+
+ @Transactional(readOnly=false)
+ protected void addItem(Integer shoppingId, IItem item)
+ {
+ IShoppingCartLineDao sclDao = getShoppingCartLineDaoImpl();
+ IShoppingCartDao scDao = getShoppingCartDaoImpl();
+
+ IShoppingCartLine scl = sclDao.getBySCandItem( shoppingId,
+ item.getIId() );
+
+ if ( scl != null )
+ {
+ scl.setSclQty( scl.getSclQty() + 1 );
+ sclDao.shrani( scl );
+ }
+ else
+ {
+ scl = sclDao.getObject();
+ scl.setItem( item );
+ scl.setSclQty( 1 );
+ IShoppingCart sc = (IShoppingCart) scDao.findById( shoppingId );
+ scl.setShoppingCart( sc );
+ sclDao.shrani( scl );
+
+ sc.getShoppingCartLines().add( scl );
+ scDao.shrani( sc );
+ }
+
+ }
+
+ @Override
+ @Transactional(readOnly=false)
+ public BuyConfirmResult doBuyConfirm(Integer shoppingId,
+ Integer customerId, String ccType, long ccNumber, String ccName,
+ Date ccExpiry, String shipping, String street1, String street2,
+ String city, String state, String zip, String country)
+ {
+
+ ICustomerDao customerDao = getCustomerDaoImpl();
+ IShoppingCartDao shoppingCartDao = getShoppingCartDaoImpl();
+
+ IShoppingCart sc = shoppingCartDao.findById( shoppingId );
+ ICustomer customer = customerDao.findById( customerId );
+
+ double cDiscount = getCDiscount( customerId );
+ IShoppingCart cart = getCart( shoppingId, cDiscount );
+ IAddress address = saveAddress( street1, street2, city, state, zip,
+ country );
+
+ IOrders order = saveOrder( address, customer, shipping, sc, cDiscount );
+
+ saveCcXacts( order, ccType, ccNumber, ccName, ccExpiry, cart, address );
+
+ clearCart( shoppingId );
+
+ return new BuyConfirmResult( order, sc );
+ }
+
+ @Override
+ @Transactional(readOnly=false)
+ public BuyConfirmResult doBuyConfirm(Integer shoppingId,
+ Integer customerId, String ccType, Long ccNumber, String ccName,
+ Date ccExpiry, String shipping)
+ {
+ double discount = getCDiscount( customerId );
+ IShoppingCart sc = getCart( shoppingId, discount );
+
+ ICustomerDao customerDao = getCustomerDaoImpl();
+ ICustomer customer = customerDao.findById( customerId );
+
+ IAddress address = customer.getAddress();
+
+ IOrders order = saveOrder( address, customer, shipping, sc, discount );
+ saveCcXacts( order, ccType, ccNumber, ccName, ccExpiry, sc, address );
+ clearCart( shoppingId );
+
+ return new BuyConfirmResult( order, sc );
+ }
+
+ @Transactional(readOnly=false)
+ protected void clearCart(Integer shoppingId)
+ {
+ IShoppingCartDao scDao = getShoppingCartDaoImpl();
+ IShoppingCart sc = (IShoppingCart) scDao.findById( shoppingId );
+
+ IShoppingCartLineDao sclDao = getShoppingCartLineDaoImpl();
+
+ Set<IShoppingCartLine> res = sc.getShoppingCartLines();
+
+ if( res != null && !res.isEmpty() )
+ {
+ for ( IShoppingCartLine scl : res )
+ {
+ sclDao.delete( scl );
+ }
+ }
+ }
+
+ @Transactional(readOnly=false)
+ protected ICcXacts saveCcXacts(IOrders order, String ccType, long ccNumber,
+ String ccName, Date ccExpiry, IShoppingCart cart, IAddress address)
+ {
+ if ( ccType.length() > 10 )
+ ccType = ccType.substring( 0, 10 );
+
+ if ( ccName.length() > 30 )
+ ccName = ccName.substring( 0, 30 );
+
+ ICcXactsDao ccXactsDao = getCcXactsDaoImpl();
+
+ ICcXacts ccXacts = ccXactsDao.getObject();
+ ccXacts.setCountry( address.getCountry() );
+ ccXacts.setOrders( order );
+ ccXacts.setCxType( ccType );
+ ccXacts.setCxNum( (int) ccNumber );
+ ccXacts.setCxName( ccName );
+ ccXacts.setCxExpiry( ccExpiry );
+ ccXacts.setCxXactAmt( calculateTotal( cart ) );
+ ccXacts.setCxXactDate( new Date() );
+ ccXacts.setCountry( address.getCountry() );
+
+ ccXactsDao.shrani( ccXacts );
+
+ return ccXacts;
+ }
+
+ @Transactional(readOnly=false)
+ protected IAddress saveAddress(String street1, String street2, String city,
+ String state, String zip, String country)
+ {
+ IAddressDao addressDao = getAddressDaoImpl();
+ ICountryDao countryDao = getCountryDaoImpl();
+
+ IAddress address = addressDao.getObject();
+
+ address.setAddrStreet1( street1 );
+ address.setAddrStreet2( street2 );
+ address.setAddrCity( city );
+ address.setAddrState( state );
+ address.setAddrZip( zip );
+
+ address.setCountry( countryDao.getByName( country ) );
+ addressDao.shrani( address );
+
+ return address;
+ }
+
+ @Transactional(readOnly=false)
+ protected IOrders saveOrder(IAddress address, ICustomer customer,
+ String shipping, IShoppingCart sc, double discount)
+ {
+ IOrdersDao ordersDao = getOrdersDaoImpl();
+ IOrderLineDao orderLineDao = getOrderLineDaoImpl();
+ Calendar cal = Calendar.getInstance();
+ Random rand = new Random();
+
+ IOrders order = ordersDao.getObject();
+ order.setCustomer( customer );
+ order.setOTax( 8.25 );
+ order.setODate( new Date() );
+ order.setAddressByOBillAddrId( customer.getAddress() );
+ order.setAddressByOShipAddrId( address );
+
+ cal.add( Calendar.DATE, rand.nextInt( 7 ) );
+ order.setOShipDate( cal.getTime() );
+ order.setOShipType( shipping );
+ order.setOStatus( "PENDING" );
+ order.setOTotal( calculateTotal( sc ) );
+ // TODO: order.setOSubTotal( calculateSubTotal(sc) );
+
+ order.setOSubTotal( calculateTotal( sc ) );
+ ordersDao.shrani( order );
+
+ Set<IShoppingCartLine> res = sc.getShoppingCartLines();
+
+ if( res != null && !res.isEmpty() )
+ {
+ for ( IShoppingCartLine scl : res)
+ {
+ IOrderLine ol = orderLineDao.getObject();
+ ol.setItem( scl.getItem() );
+ ol.setOlComment( getRandomString( 20, 100 ) );
+ ol.setOlDiscount( discount );
+ ol.setOlQty( scl.getSclQty() );
+ ol.setOrders( order );
+ order.getOrderLines().add( ol );
+ orderLineDao.shrani( ol );
+ }
+ }
+
+ ordersDao.shrani( order );
+
+ return order;
+ }
+
+ public String getRandomString(int min, int max)
+ {
+ String newstring = new String();
+ Random rand = new Random();
+ int i;
+ final char[] chars = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', '#', '$', '%', '^',
+ '&', '*', '(', ')', '_', '-', '=', '+', '{', '}', '[', ']',
+ '|', ':', ';', ',', '.', '?', '/', '~', ' ' }; // 79
+ // characters
+ int strlen = (int) Math.floor( rand.nextDouble() * ( max - min + 1 ) );
+ strlen += min;
+ for ( i = 0; i < strlen; i++ )
+ {
+ char c = chars[(int) Math.floor( rand.nextDouble() * 79 )];
+ newstring = newstring.concat( String.valueOf( c ) );
+ }
+ return newstring;
+ }
+
+ protected double calculateTotal(IShoppingCart sc)
+ {
+ double total = 0;
+ Set<IShoppingCartLine> res = sc.getShoppingCartLines();
+
+ if( res != null && !res.isEmpty() )
+ {
+ for ( IShoppingCartLine scl : res )
+ {
+ if( scl != null )
+ {
+ total += scl.getItem().getICost();
+ }
+ }
+ }
+
+ return total;
+ }
+
+ protected double getCDiscount(Integer customerId)
+ {
+ ICustomerDao customerDao = getCustomerDaoImpl();
+ ICustomer customer = customerDao.findById( customerId );
+
+ return customer.getCDiscount();
+ }
+
+ @Override
+ public List searchByAuthor(String keyword)
+ {
+ IAuthorDao authorDao = getAuthorDaoImpl();
+ IItemDao itemDao = getItemDaoImpl();
+
+ List<IAuthor> authors = authorDao.findBySoundexLname( keyword );
+
+ List<IItem> items = new ArrayList<IItem>();
+
+ for ( IAuthor author : authors )
+ {
+ if ( items.size() >= 50 )
+ {
+ break;
+ }
+
+ items.addAll( itemDao.findAllByAuthor( author ) );
+ }
+
+ return items;
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/BuyConfirmResult.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/BuyConfirmResult.java
new file mode 100644
index 0000000..7d4be6a
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/BuyConfirmResult.java
@@ -0,0 +1,42 @@
+package eu.cloudscale.showcase.db;
+
+import eu.cloudscale.showcase.db.model.IOrders;
+import eu.cloudscale.showcase.db.model.IShoppingCart;
+
+
+public class BuyConfirmResult
+{
+ public IOrders order;
+ public IShoppingCart cart;
+
+ public BuyConfirmResult(IOrders order2, IShoppingCart sc)
+ {
+ order = order2;
+ cart = sc;
+ }
+
+
+ public IOrders getOrder()
+ {
+ return order;
+ }
+
+
+ public void setOrder(IOrders order)
+ {
+ this.order = order;
+ }
+
+
+ public IShoppingCart getCart()
+ {
+ return cart;
+ }
+
+
+ public void setCart(IShoppingCart cart)
+ {
+ this.cart = cart;
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/common/ContextHelper.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/common/ContextHelper.java
new file mode 100644
index 0000000..461e456
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/common/ContextHelper.java
@@ -0,0 +1,22 @@
+package eu.cloudscale.showcase.db.common;
+
+import org.springframework.context.support.GenericXmlApplicationContext;
+
+
+public class ContextHelper
+{
+ private static GenericXmlApplicationContext ctx = null;
+
+ public static GenericXmlApplicationContext getApplicationContext()
+ {
+ if( ctx == null)
+ {
+ ctx = new GenericXmlApplicationContext();
+ ctx.load("classpath:app-context.xml");
+ ctx.refresh();
+ }
+
+ return ctx;
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/common/DatabaseHelper.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/common/DatabaseHelper.java
new file mode 100644
index 0000000..1221688
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/common/DatabaseHelper.java
@@ -0,0 +1,37 @@
+package eu.cloudscale.showcase.db.common;
+
+import eu.cloudscale.showcase.db.IService;
+
+
+public class DatabaseHelper
+{
+
+ private static IService db = null;
+ private static String driverName = null;
+
+ public static IService getDatabase()
+ {
+ if( db == null )
+ {
+ db = (IService) ContextHelper.getApplicationContext().getBean( "service" );
+ }
+
+ return db;
+
+ }
+
+ public static String getDriverName()
+ {
+ return driverName;
+ }
+
+ public static void loadMySQLDriver()
+ {
+ try {
+ Class.forName("com.mysql.jdbc.Driver");
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/common/Soundex.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/common/Soundex.java
new file mode 100644
index 0000000..da72e86
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/common/Soundex.java
@@ -0,0 +1,92 @@
+package eu.cloudscale.showcase.db.common;
+
+public class Soundex
+{
+
+ public static String soundex(String s)
+ {
+ char[] x = s.toUpperCase().toCharArray();
+ char firstLetter = x[0];
+
+ // convert letters to numeric code
+ for ( int i = 0; i < x.length; i++ )
+ {
+ switch ( x[i] )
+ {
+ case 'B':
+ case 'F':
+ case 'P':
+ case 'V':
+ {
+ x[i] = '1';
+ break;
+ }
+
+ case 'C':
+ case 'G':
+ case 'J':
+ case 'K':
+ case 'Q':
+ case 'S':
+ case 'X':
+ case 'Z':
+ {
+ x[i] = '2';
+ break;
+ }
+
+ case 'D':
+ case 'T':
+ {
+ x[i] = '3';
+ break;
+ }
+
+ case 'L':
+ {
+ x[i] = '4';
+ break;
+ }
+
+ case 'M':
+ case 'N':
+ {
+ x[i] = '5';
+ break;
+ }
+
+ case 'R':
+ {
+ x[i] = '6';
+ break;
+ }
+
+ default:
+ {
+ x[i] = '0';
+ break;
+ }
+ }
+ }
+
+ // remove duplicates
+ String output = "" + firstLetter;
+ for ( int i = 1; i < x.length; i++ )
+ if ( x[i] != x[i - 1] && x[i] != '0' )
+ output += x[i];
+
+ // pad with 0's or truncate
+ output = output + "0000";
+ return output.substring( 0, 4 );
+ }
+
+ public static void main(String[] args)
+ {
+ String name1 = args[0];
+ String name2 = args[1];
+ String code1 = soundex( name1 );
+ String code2 = soundex( name2 );
+ System.out.println( code1 + ": " + name1 );
+ System.out.println( code2 + ": " + name2 );
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/AddressDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/AddressDaoImpl.java
new file mode 100644
index 0000000..3290e16
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/AddressDaoImpl.java
@@ -0,0 +1,46 @@
+package eu.cloudscale.showcase.db.dao.hibernate.impl;
+
+import java.util.List;
+
+import org.hibernate.SessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import eu.cloudscale.showcase.db.dao.IAddressDao;
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.hibernate.Address;
+
+@Repository
+@Transactional(readOnly=true)
+public class AddressDaoImpl extends DaoImpl<IAddress> implements IAddressDao
+{
+ public AddressDaoImpl()
+ {
+ System.out.println("AddressDaoImpl constructor called!");
+ }
+
+ @Autowired
+ public AddressDaoImpl(SessionFactory sessionFactory)
+ {
+ super(sessionFactory);
+ }
+
+ @Override
+ public List<IAddress> findAll()
+ {
+ return null;
+ }
+
+ @Override
+ public IAddress findById(int id)
+ {
+ return (IAddress) getCurrentSession().get( Address.class, id );
+ }
+
+ @Override
+ public IAddress getObject()
+ {
+ return new Address();
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/AuthorDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/AuthorDaoImpl.java
new file mode 100644
index 0000000..ce076ce
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/AuthorDaoImpl.java
@@ -0,0 +1,64 @@
+package eu.cloudscale.showcase.db.dao.hibernate.impl;
+
+import java.util.List;
+
+import org.hibernate.Query;
+import org.hibernate.SessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import eu.cloudscale.showcase.db.dao.IAuthorDao;
+import eu.cloudscale.showcase.db.model.IAuthor;
+import eu.cloudscale.showcase.db.model.hibernate.Author;
+
+@Repository
+@Transactional(readOnly=true)
+public class AuthorDaoImpl extends DaoImpl<IAuthor> implements IAuthorDao
+{
+ public AuthorDaoImpl()
+ {
+// super( (SessionFactory) ContextHelper.getApplicationContext().getBean( "sessionFactory" ) );
+ }
+
+ @Autowired
+ public AuthorDaoImpl(SessionFactory sessionFactory)
+ {
+ super( sessionFactory );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public List<IAuthor> findAll()
+ {
+ String hql = "FROM Author";
+ Query q = getCurrentSession().createQuery( hql );
+ return q.list();
+ }
+
+ @Override
+ public IAuthor findById(int id)
+ {
+ return (IAuthor) getCurrentSession().get( Author.class, id );
+ }
+
+ @Override
+ public IAuthor getObject()
+ {
+ return new Author();
+ }
+
+ @Override
+ public List<IAuthor> findBySoundexLname(String keyword)
+ {
+ String hql = "SELECT A FROM Author as A, Item as I WHERE substring(soundex(A.ALname),0,4)=substring(soundex(:keyword),0,4) AND I.author.AId=A.AId ORDER BY I.ITitle";
+
+ Query query = getCurrentSession().createQuery( hql );
+ query.setParameter( "keyword", keyword );
+ query.setMaxResults( 50 );
+
+ List res = (List<Author>) query.list();
+
+ return res;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/CcXactsDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/CcXactsDaoImpl.java
new file mode 100644
index 0000000..592d195
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/CcXactsDaoImpl.java
@@ -0,0 +1,67 @@
+package eu.cloudscale.showcase.db.dao.hibernate.impl;
+
+
+import java.util.List;
+
+import org.hibernate.Query;
+import org.hibernate.SessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import eu.cloudscale.showcase.db.dao.ICcXactsDao;
+import eu.cloudscale.showcase.db.model.ICcXacts;
+import eu.cloudscale.showcase.db.model.hibernate.CcXacts;
+
+@Repository
+@Transactional(readOnly=true)
+public class CcXactsDaoImpl extends DaoImpl<ICcXacts> implements ICcXactsDao
+{
+
+ public CcXactsDaoImpl()
+ {
+// super( (SessionFactory) ContextHelper.getApplicationContext().getBean( "sessionFactory" ) );
+ }
+
+ @Autowired
+ public CcXactsDaoImpl(SessionFactory sessionFactory)
+ {
+ super( sessionFactory );
+ }
+
+ @Override
+ public ICcXacts getObject()
+ {
+ return new CcXacts();
+ }
+
+ @SuppressWarnings( "rawtypes" )
+ @Override
+ public int getLastCcXactsId()
+ {
+ String hql = "SELECT CX_ID FROM cc_xacts ORDER BY CX_ID DESC";
+
+ Query query = getCurrentSession().createQuery( hql );
+ query.setMaxResults( 1 );
+ List res = query.list();
+
+ return ((ICcXacts) res.get( 0 )).getId();
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public ICcXacts findById(Integer id)
+ {
+ String hql = "SELECT * FROM cc_xacts WHERE CX_ID = :id";
+ Query query = getCurrentSession().createQuery( hql );
+ query.setParameter( "id", id );
+
+ List<CcXacts> res = query.list();
+
+ if( res.isEmpty() )
+ return null;
+
+ return res.get( 0 );
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/CountryDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/CountryDaoImpl.java
new file mode 100644
index 0000000..f9c99e6
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/CountryDaoImpl.java
@@ -0,0 +1,72 @@
+package eu.cloudscale.showcase.db.dao.hibernate.impl;
+
+import java.util.List;
+
+import org.hibernate.Query;
+import org.hibernate.SessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import eu.cloudscale.showcase.db.dao.ICountryDao;
+import eu.cloudscale.showcase.db.model.ICountry;
+import eu.cloudscale.showcase.db.model.hibernate.Country;
+
+@Repository
+@Transactional(readOnly=true)
+public class CountryDaoImpl extends DaoImpl<ICountry> implements ICountryDao
+{
+ private String tableName = "country";
+
+ public CountryDaoImpl()
+ {
+// super( (SessionFactory) ContextHelper.getApplicationContext().getBean( "sessionFactory" ) );
+ }
+
+ @Autowired
+ public CountryDaoImpl(SessionFactory sessionFactory)
+ {
+ super( sessionFactory );
+ }
+
+ @Override
+ public ICountry findById(int id)
+ {
+// String hql = "FROM Country C WHERE C.coId = :coId";
+// Query q = this.session.createQuery(hql);
+// q.setParameter("coId", id);
+// List<Country> res = (List<Country>) q.list();
+// return res.get(0);
+ return (ICountry) getCurrentSession().get( Country.class, id );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public ICountry getByName(String country)
+ {
+ String hql = "SELECT C FROM Country as C WHERE C.coName = :countryName";
+ Query query = getCurrentSession().createQuery( hql );
+ query.setParameter( "countryName", country );
+
+ List<Query> res = query.list();
+ if( res.isEmpty() )
+ {
+ return null;
+ }
+
+ return (ICountry) res.get( 0 );
+ }
+
+ @Override
+ public ICountry getObject()
+ {
+ return new Country();
+ }
+
+ @Override
+ public void createTable()
+ {
+ String query = "CREATE TABLE IF NOT EXISTS " + this.tableName;
+ getCurrentSession().createSQLQuery( query );
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/CustomerDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/CustomerDaoImpl.java
new file mode 100644
index 0000000..fe42bca
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/CustomerDaoImpl.java
@@ -0,0 +1,75 @@
+package eu.cloudscale.showcase.db.dao.hibernate.impl;
+
+import java.util.List;
+
+import org.hibernate.Query;
+import org.hibernate.SessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import eu.cloudscale.showcase.db.dao.ICustomerDao;
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.model.hibernate.Customer;
+
+@Repository
+@Transactional(readOnly=true)
+public class CustomerDaoImpl extends DaoImpl<ICustomer> implements ICustomerDao
+{
+
+ public CustomerDaoImpl()
+ {
+// super( (SessionFactory) ContextHelper.getApplicationContext().getBean( "sessionFactory" ) );
+// System.out.println("Normal constructor called!");
+ }
+
+ @Autowired
+ public CustomerDaoImpl(SessionFactory sessionFactory)
+ {
+ super( sessionFactory );
+ }
+
+ @SuppressWarnings( "rawtypes" )
+ @Override
+ public ICustomer getUserBy(String username, String password)
+ {
+ String query = "SELECT C FROM Customer as C WHERE C.CUname = :username AND C.CPasswd = :passwd";
+
+ Query q = getCurrentSession().createQuery( query );
+ q.setMaxResults( 1 );
+ q.setParameter( "username", username );
+ q.setParameter( "passwd", password );
+ List res = q.list();
+
+ if( res.isEmpty() )
+ return null;
+
+ return (ICustomer) q.list().get( 0 );
+ }
+
+
+ @Override
+ public ICustomer getObject()
+ {
+ return new Customer();
+ }
+
+ @Override
+ public ICustomer findById(Integer id)
+ {
+ return (ICustomer) getCurrentSession().get( Customer.class, id );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public List<ICustomer> findByAddress(IAddress address)
+ {
+ String query = "SELECT C FROM Customer as C WHERE C.address = :address";
+
+ Query q = getCurrentSession().createQuery( query );
+ q.setParameter( "address", address );
+
+ return q.list();
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/DaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/DaoImpl.java
new file mode 100644
index 0000000..1d5aca3
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/DaoImpl.java
@@ -0,0 +1,57 @@
+package eu.cloudscale.showcase.db.dao.hibernate.impl;
+
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.springframework.transaction.annotation.Transactional;
+
+import eu.cloudscale.showcase.db.dao.IDao;
+
+@Transactional(readOnly=true)
+public class DaoImpl<T> implements IDao<T>
+{
+ protected int count = 1;
+ protected SessionFactory sessionFactory;
+
+ public DaoImpl()
+ {
+ }
+
+ public DaoImpl(SessionFactory sessionFactory)
+ {
+ this.sessionFactory = sessionFactory;
+ }
+
+
+ protected final Session getCurrentSession()
+ {
+ return this.sessionFactory.getCurrentSession();
+ }
+
+ @Override
+ @Transactional(readOnly=false)
+ public T shrani(T object)
+ {
+ getCurrentSession().saveOrUpdate( object );
+ return object;
+ }
+
+ @Override
+ public void finish()
+ {
+ }
+
+ @Override
+ public T getObject()
+ {
+ try
+ {
+ throw new UnsupportedOperationException( "Implement in DAO implementation!" );
+ }
+ catch ( UnsupportedOperationException e )
+ {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/ItemDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/ItemDaoImpl.java
new file mode 100644
index 0000000..3dfbe77
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/ItemDaoImpl.java
@@ -0,0 +1,251 @@
+package eu.cloudscale.showcase.db.dao.hibernate.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hibernate.CacheMode;
+import org.hibernate.Hibernate;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import eu.cloudscale.showcase.db.dao.IItemDao;
+import eu.cloudscale.showcase.db.model.IAuthor;
+import eu.cloudscale.showcase.db.model.IItem;
+import eu.cloudscale.showcase.db.model.hibernate.Item;
+
+@Repository
+@Transactional(readOnly=true)
+public class ItemDaoImpl extends DaoImpl<IItem> implements IItemDao
+{
+
+ public ItemDaoImpl()
+ {
+ // super( (SessionFactory)
+ // ContextHelper.getApplicationContext().getBean( "sessionFactory" ) );
+ }
+
+ @Autowired
+ public ItemDaoImpl(SessionFactory sessionFactory)
+ {
+ super( sessionFactory );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public List<IItem> findAll()
+ {
+ String hql = "FROM Item";
+ Query q = getCurrentSession().createQuery( hql );
+ q.setMaxResults( 20 );
+ return (List<IItem>) q.list();
+ }
+
+ @SuppressWarnings( "unused" )
+ @Override
+ public IItem findById(int id)
+ {
+ String hql = "SELECT I, A FROM Item I, Author A WHERE I.IId = :itemId AND A.AId = I.author.AId";
+ Query q = getCurrentSession().createQuery( hql );
+ q.setParameter( "itemId", id );
+ @SuppressWarnings( "rawtypes" )
+ List res = q.list();
+ if ( q.list().get( 0 ) == null )
+ return null;
+
+ IItem item = (Item) ( (Object[]) q.list().get( 0 ) )[0];
+ // Hibernate.initialize( item.getShoppingCartLines() );
+ // Hibernate.initialize( item.getOrderLines());
+ return item;
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public List<IItem> getPromotional()
+ {
+ String hql = "FROM Item I ORDER BY RAND()";
+ Query q = getCurrentSession().createQuery( hql );
+ q.setMaxResults( 1 );
+
+ List<IItem> res = (List<IItem>) q.list();
+
+ ArrayList<IItem> promotional = new ArrayList<IItem>();
+//
+// promotional.add( findById( 7296 ) );
+//
+// promotional.add( findById( 6547 ) );
+//
+// promotional.add( findById( 446 ) );
+//
+// promotional.add( findById( 4807 ) );
+//
+// promotional.add( findById( 5706 ) );
+ promotional.add( findById( res.get( 0 ).getIRelated1() ) );
+
+ promotional.add( findById( res.get( 0 ).getIRelated2() ) );
+
+ promotional.add( findById( res.get( 0 ).getIRelated3() ) );
+
+ promotional.add( findById( res.get( 0 ).getIRelated4() ) );
+
+ promotional.add( findById( res.get( 0 ).getIRelated5() ) );
+
+ return promotional;
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ @Transactional( readOnly = true )
+ public List<IItem> getNewProducts(String category)
+ {
+ Session session = sessionFactory.getCurrentSession();
+ Query query = session
+ .createQuery( "SELECT I, A FROM Item as I, Author as A WHERE I.author.AId = A.AId AND I.ISubject = :category "
+ + "ORDER BY I.IPubDate DESC, I.ITitle" );
+ query.setString( "category", category );
+ query.setMaxResults( 50 );
+ ArrayList<IItem> newProducts = new ArrayList<IItem>();
+
+ List<Object[]> res = query.list();
+ for ( int i = 0; i < res.size(); i++ )
+ {
+ newProducts.add( (Item) ( res.get( i )[0] ) );
+ }
+ return newProducts;
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Transactional( readOnly = true )
+ public List<Object[]> getBestSellers(String category)
+ {
+ Session session = sessionFactory.openSession();
+
+ Query query =
+ session.createQuery("SELECT I.IId, A.AFname, A.ALname, I.ITitle, SUM(OL.olQty) AS val " +
+ "FROM OrderLine as OL, Item as I, Author as A " +
+ "WHERE " +
+ "I.author.AId = A.AId AND " +
+ "I.IId = OL.item.IId AND " +
+ "I.ISubject = :category " +
+ "GROUP BY OL.item.IId " +
+ "ORDER BY val DESC");
+
+// Query query = session
+// .createSQLQuery(
+// "SELECT i_id as a, i_title as b, a_fname as c, a_lname as d, SUM(ol_qty) AS val "
+// + "FROM "
+// + "orders, order_line, item, author "
+// + "WHERE "
+// + "order_line.ol_o_id = orders.o_id AND item.i_id = order_line.ol_i_id "
+// + "AND item.i_subject = :category AND item.i_a_id = author.a_id GROUP BY i_id "
+// + "ORDER BY orders.o_date, val DESC" )
+// .addScalar( "a" ).addScalar( "b" ).addScalar( "c" )
+// .addScalar( "d" ).addScalar( "val" );
+
+ query.setParameter( "category", category );
+ query.setMaxResults( 50 );
+
+ long start = System.nanoTime();
+ List<Object[]> res = query.list();
+ System.out.println( "[best-sellers] Category = " + category + ", cas izvajanja = "
+ + ( System.nanoTime() - start ) / 1E9 );
+
+ return res;
+
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public IItem getRandomItem()
+ {
+ String hql = "SELECT I FROM Item as I ORDER BY RAND()";
+ Query query = getCurrentSession().createQuery( hql );
+ query.setMaxResults( 1 );
+
+ List<Object> res = query.list();
+ if ( res.isEmpty() )
+ {
+ return null;
+ }
+
+ return (IItem) res.get( 0 );
+ }
+
+ @Override
+ public IItem getObject()
+ {
+ return new Item();
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public List<IItem> findAllByAuthor(IAuthor author)
+ {
+ String hql = "SELECT I FROM Item as I WHERE I.author = :author ORDER BY I.ITitle";
+ Query query = getCurrentSession().createQuery( hql );
+
+ query.setParameter( "author", author );
+ query.setMaxResults( 50 );
+ // query.setCacheable( true );
+
+ List<IItem> res = query.list();
+
+ ArrayList<IItem> items = new ArrayList<IItem>();
+ for ( IItem item : res )
+ {
+ Hibernate.initialize( item.getAuthor() );
+ items.add( item );
+ }
+
+ return items;
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public List<IItem> findAllByTitle(String keyword)
+ {
+ String hql = "SELECT I FROM Item as I, Author as A WHERE I.author.AId = A.AId AND substring(soundex(I.ITitle), 0, 4) = substring(soundex(:title), 0, 4) ORDER BY I.ITitle";
+
+ Query query = getCurrentSession().createQuery( hql );
+
+ query.setParameter( "title", keyword );
+ query.setMaxResults( 50 );
+ // query.setCacheable( true );
+
+ List<IItem> res = query.list();
+
+ for ( IItem item : res )
+ {
+ Hibernate.initialize( item.getAuthor() );
+ }
+
+ return res;
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public List<IItem> findAllBySubject(String keyword)
+ {
+ String hql = "SELECT I FROM Item as I WHERE I.ISubject = :subject ORDER BY I.ITitle";
+
+ Query query = getCurrentSession().createQuery( hql );
+
+ query.setParameter( "subject", keyword );
+ query.setMaxResults( 50 );
+ // query.setCacheable( true );
+
+ List<IItem> res = query.list();
+ for ( IItem item : res )
+ {
+ Hibernate.initialize( item.getAuthor() );
+ }
+
+ return res;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/OrderLineDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/OrderLineDaoImpl.java
new file mode 100644
index 0000000..365978b
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/OrderLineDaoImpl.java
@@ -0,0 +1,50 @@
+package eu.cloudscale.showcase.db.dao.hibernate.impl;
+
+import java.util.List;
+
+import org.hibernate.Query;
+import org.hibernate.SessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import eu.cloudscale.showcase.db.dao.IOrderLineDao;
+import eu.cloudscale.showcase.db.model.IOrderLine;
+import eu.cloudscale.showcase.db.model.IOrders;
+import eu.cloudscale.showcase.db.model.hibernate.OrderLine;
+
+@Repository
+@Transactional(readOnly=true)
+public class OrderLineDaoImpl extends DaoImpl<IOrderLine> implements IOrderLineDao
+{
+
+ public OrderLineDaoImpl()
+ {
+// super( (SessionFactory) ContextHelper.getApplicationContext().getBean( "sessionFactory" ) );
+ }
+
+ @Autowired
+ public OrderLineDaoImpl(SessionFactory sessionFactory)
+ {
+ super( sessionFactory );
+ }
+
+ @Override
+ public IOrderLine getObject()
+ {
+ return new OrderLine();
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public List<IOrderLine> findAllByOrder(IOrders orders)
+ {
+ String hql = "SELECT OL FROM OrderLine as OL WHERE OL.orders = :order";
+
+ Query query = getCurrentSession().createQuery( hql );
+ query.setParameter( "order", orders );
+
+ return query.list();
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/OrdersDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/OrdersDaoImpl.java
new file mode 100644
index 0000000..d36bd24
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/OrdersDaoImpl.java
@@ -0,0 +1,173 @@
+package eu.cloudscale.showcase.db.dao.hibernate.impl;
+
+import java.util.List;
+
+import org.hibernate.Query;
+import org.hibernate.SessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import eu.cloudscale.showcase.db.dao.IOrdersDao;
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.model.IOrders;
+import eu.cloudscale.showcase.db.model.hibernate.Orders;
+
+@Repository
+@Transactional(readOnly=true)
+public class OrdersDaoImpl extends DaoImpl<IOrders> implements IOrdersDao
+{
+ public OrdersDaoImpl()
+ {
+// super( (SessionFactory) ContextHelper.getApplicationContext().getBean( "sessionFactory" ) );
+ }
+
+ @Autowired
+ public OrdersDaoImpl(SessionFactory sessionFactory)
+ {
+ super( sessionFactory );
+ }
+
+ @Override
+ public IOrders getObject()
+ {
+ return new Orders();
+ }
+
+ @SuppressWarnings( { "rawtypes" } )
+ @Override
+ public IOrders getMostRecentOrder(ICustomer customer)
+ {
+
+ String hql16 = "SELECT O FROM Orders as O, Customer as C WHERE O.customer.CId = C.CId AND C.CUname = :cid ORDER BY O.ODate, O.OId DESC";
+ Query query16 = getCurrentSession().createQuery( hql16 );
+ query16.setMaxResults( 1 );
+ query16.setParameter( "cid", customer.getCId() );
+ List res16 = query16.list();
+
+ if( res16 == null || res16.isEmpty() )
+ {
+ return null;
+ }
+
+ IOrders order = (IOrders) res16.get( 0 );
+// Hibernate.initialize( order.getOrderLines() );
+
+ return order;
+//// SELECT O FROM Customer as C, Orders as O WHERE C.CId = O.OCId AND C.CUname = 'SE' ORDER BY O.ODate, O.OId DESC
+// String hql1 = "SELECT O FROM Customer as C, Orders as O"
+// + " WHERE C.CId = O.customer.CId"
+// + " AND C.CUname = :username"
+// + " ORDER BY O.ODate, O.OId DESC";
+// Query query = getCurrentSession().createQuery( hql1 );
+// query.setParameter( "username", customerUsername );
+// query.setMaxResults( 1 );
+// if( query.list().isEmpty() )
+// return null;
+//
+// IOrders order = (IOrders) query.list().get( 0 );
+//
+// String hql2 = "SELECT O, C, CX, SHIP, SHIP_CO, BILL, BILL_CO FROM"
+// + " Orders as O, "
+// + " Customer as C,"
+// + " CcXacts as CX, "
+// + " Address as SHIP, "
+// + " Address as BILL, "
+// + " Country as SHIP_CO, "
+// + " Country as BILL_CO "
+// + " WHERE O.OId = :orderId"
+// + " AND CX.id.cxOId = O.OId"
+// + " AND C.CId = O.customer.CId"
+// + " AND O.addressByOBillAddrId.addrId = BILL.addrId"
+// + " AND BILL.country.coId = BILL_CO.coId"
+// + " AND O.addressByOShipAddrId.addrId = SHIP.addrId"
+// + " AND SHIP.country.coId = SHIP_CO.coId"
+// + " ORDER BY O.ODate, O.OId DESC";
+// query = getCurrentSession().createQuery( hql2 );
+// query.setMaxResults(1);
+// query.setParameter("orderId", order.getOId());
+//
+//
+// List res = query.list();
+// if( res.isEmpty() )
+// return null;
+//
+// order = new Orders((Object[]) query.list().get( 0 ));
+//
+// return order;
+ }
+
+ @Override
+ public IOrders findById(Integer cxOId)
+ {
+ return (IOrders) getCurrentSession().get( Orders.class, cxOId );
+ }
+
+// @Override
+// public Orders getMostRecentOrder(String customerUsername, List<OrderLine> orderLines)
+// {
+// String hql1 = "SELECT o_id "
+// + "FROM customer, orders "
+// + "WHERE customer.c_id = orders.o_c_id "
+// + "AND c_uname = ? "
+// + "ORDER BY o_date, orders.o_id DESC "
+// + "LIMIT 0,1";
+// Query query = getCurrentSession().createQuery( hql1 );
+// query.setParameter( "username", customerUsername );
+// query.setMaxResults( 1 );
+// if( query.list().isEmpty() )
+// return null;
+//
+// Orders order = (Orders) query.list().get( 0 );
+//
+// String hql2 = "SELECT orders.*, customer.*, "
+// + " cc_xacts.cx_type, "
+// + " ship.addr_street1 AS ship_addr_street1, "
+// + " ship.addr_street2 AS ship_addr_street2, "
+// + " ship.addr_state AS ship_addr_state, "
+// + " ship.addr_zip AS ship_addr_zip, "
+// + " ship_co.co_name AS ship_co_name, "
+// + " bill.addr_street1 AS bill_addr_street1, "
+// + " bill.addr_street2 AS bill_addr_street2, "
+// + " bill.addr_state AS bill_addr_state, "
+// + " bill.addr_zip AS bill_addr_zip, "
+// + " bill_co.co_name AS bill_co_name "
+// + "FROM customer, orders, cc_xacts,"
+// + " address AS ship, "
+// + " country AS ship_co, "
+// + " address AS bill, "
+// + " country AS bill_co "
+// + "WHERE orders.o_id = :orderId "
+// + " AND cx_o_id = orders.o_id "
+// + " AND customer.c_id = orders.o_c_id "
+// + " AND orders.o_bill_addr_id = bill.addr_id "
+// + " AND bill.addr_co_id = bill_co.co_id "
+// + " AND orders.o_ship_addr_id = ship.addr_id "
+// + " AND ship.addr_co_id = ship_co.co_id "
+// + " AND orders.o_c_id = customer.c_id";
+// query = getCurrentSession().createQuery( hql2 );
+// query.setMaxResults(1);
+// query.setParameter("orderId", order.getOId());
+//
+// List res = query.list();
+// if( res.isEmpty() )
+// return null;
+//
+// order = new Orders((Object[]) query.list().get( 0 ));
+//
+// String hql3 = "SELECT * "
+// + "FROM order_line, item "
+// + "WHERE ol_o_id = :orderId " + "AND ol_i_id = i_id";
+//
+// query = getCurrentSession().createQuery( hql3 );
+// query.setParameter( "orderId", order.getOId() );
+// List<Object[]> res3 = query.list();
+//
+// for( Object[] obj : res3 )
+// {
+// orderLines.add( (OrderLine) obj[0] );
+// }
+//
+// return order;
+// }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/ShoppingCartDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/ShoppingCartDaoImpl.java
new file mode 100644
index 0000000..e67e099
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/ShoppingCartDaoImpl.java
@@ -0,0 +1,83 @@
+package eu.cloudscale.showcase.db.dao.hibernate.impl;
+
+import java.util.Date;
+import java.util.List;
+
+import org.hibernate.Hibernate;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import eu.cloudscale.showcase.db.dao.IShoppingCartDao;
+import eu.cloudscale.showcase.db.model.IShoppingCart;
+import eu.cloudscale.showcase.db.model.IShoppingCartLine;
+import eu.cloudscale.showcase.db.model.hibernate.ShoppingCart;
+
+@Repository
+@Transactional(readOnly=true)
+public class ShoppingCartDaoImpl extends DaoImpl<IShoppingCart> implements IShoppingCartDao
+{
+
+ public ShoppingCartDaoImpl()
+ {
+// super( (SessionFactory) ContextHelper.getApplicationContext().getBean( "sessionFactory" ) );
+ }
+
+ @Autowired
+ public ShoppingCartDaoImpl(SessionFactory sessionFactory)
+ {
+ super(sessionFactory);
+ }
+
+ @Override
+ @Transactional(readOnly=false)
+ public Integer createEmptyCart()
+ {
+ IShoppingCart sc = new ShoppingCart();
+ sc.setScTime( new Date() );
+ shrani( sc );
+
+ return sc.getScId();
+ }
+
+ @SuppressWarnings( "rawtypes" )
+ @Override
+ public IShoppingCart findById(Integer shoppingId)
+ {
+ Session session = getCurrentSession();
+ String hql = "SELECT SC FROM ShoppingCart as SC WHERE SC.scId = :scId";
+
+ Query query = session.createQuery(hql);
+ query.setParameter( "scId", shoppingId );
+
+ List res = query.list();
+ if( res.isEmpty() )
+ return null;
+
+ ShoppingCart sc = (ShoppingCart) res.get( 0 );
+ Hibernate.initialize( sc.getShoppingCartLines() );
+ return sc;
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public List<IShoppingCartLine> findAllBySC(IShoppingCart shoppingCart)
+ {
+ String hql = "SELECT SCL FROM ShoppingCartLine as SCL WHERE SCL.shoppingCart = :shoppingCart";
+
+ Query query = getCurrentSession().createQuery( hql );
+ query.setParameter( "shoppingCart", shoppingCart );
+
+ return query.list();
+ }
+
+ @Override
+ public IShoppingCart getObject()
+ {
+ return new ShoppingCart();
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/ShoppingCartLineDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/ShoppingCartLineDaoImpl.java
new file mode 100644
index 0000000..eea318c
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/hibernate/impl/ShoppingCartLineDaoImpl.java
@@ -0,0 +1,95 @@
+package eu.cloudscale.showcase.db.dao.hibernate.impl;
+
+import java.util.List;
+
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+import eu.cloudscale.showcase.db.dao.IShoppingCartLineDao;
+import eu.cloudscale.showcase.db.model.IShoppingCartLine;
+import eu.cloudscale.showcase.db.model.hibernate.ShoppingCartLine;
+
+@Repository
+@Transactional(readOnly=true)
+public class ShoppingCartLineDaoImpl extends DaoImpl<IShoppingCartLine> implements IShoppingCartLineDao
+{
+
+
+ public ShoppingCartLineDaoImpl()
+ {
+// super( (SessionFactory) ContextHelper.getApplicationContext().getBean( "sessionFactory" ) );
+ }
+
+ @Autowired
+ public ShoppingCartLineDaoImpl(SessionFactory sessionFactory)
+ {
+ super( sessionFactory );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public IShoppingCartLine getBySCandItem(Integer shoppingId, int itemId)
+ {
+ String hql1 = "SELECT SCL FROM ShoppingCartLine as SCL WHERE SCL.shoppingCart.scId = :scId AND SCL.item.IId = :itemId";
+ Query q1 = getCurrentSession().createQuery( hql1 );
+ q1.setMaxResults( 1 );
+ q1.setParameter( "scId", shoppingId );
+ q1.setParameter( "itemId", itemId);
+
+ List<Object> res = q1.list();
+ if( res.isEmpty() )
+ return null;
+
+ return (IShoppingCartLine) res.get( 0 );
+
+ }
+
+ @Override
+ public void delete(IShoppingCartLine obj)
+ {
+ Session session = getCurrentSession();
+ session.delete( obj );
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public boolean isCartEmpty(int scId)
+ {
+ String hql = "SELECT COUNT(SCL) FROM ShoppingCartLine as SCL WHERE SCL.shoppingCart.scId = :scId";
+ Query q1 = getCurrentSession().createQuery( hql );
+ q1.setMaxResults( 1 );
+ q1.setParameter( "scId", scId);
+
+ List<Long> res = q1.list();
+ if( res != null && res.get(0) == 0 )
+ return true;
+
+ return false;
+ }
+
+ @SuppressWarnings( "unchecked" )
+ @Override
+ public List<Object[]> findBySCId(Integer shoppingId)
+ {
+ String hql = "SELECT SCL, I FROM ShoppingCartLine as SCL, Item as I WHERE SCL.item.IId = I.IId AND SCL.shoppingCart.scId = :scId";
+ Query q1 = getCurrentSession().createQuery( hql );
+ q1.setMaxResults( 1 );
+ q1.setParameter( "scId", shoppingId);
+
+ List<Object[]> res = q1.list();
+ if( res.isEmpty() )
+ return null;
+
+ return res;
+ }
+
+ @Override
+ public IShoppingCartLine getObject()
+ {
+ return new ShoppingCartLine();
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IAddressDao.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IAddressDao.java
new file mode 100644
index 0000000..a66f55e
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IAddressDao.java
@@ -0,0 +1,14 @@
+package eu.cloudscale.showcase.db.dao;
+
+import java.util.List;
+
+import eu.cloudscale.showcase.db.model.IAddress;
+
+
+public interface IAddressDao extends IDao<IAddress>
+{
+ public List<IAddress> findAll();
+
+ public IAddress findById(int id);
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IAuthorDao.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IAuthorDao.java
new file mode 100644
index 0000000..a45d8d4
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IAuthorDao.java
@@ -0,0 +1,15 @@
+package eu.cloudscale.showcase.db.dao;
+
+import java.util.List;
+
+import eu.cloudscale.showcase.db.model.IAuthor;
+
+public interface IAuthorDao extends IDao<IAuthor>
+{
+ public List<IAuthor> findAll();
+
+ public IAuthor findById(int id);
+
+ public List<IAuthor> findBySoundexLname(String keyword);
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/ICcXactsDao.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/ICcXactsDao.java
new file mode 100644
index 0000000..3165388
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/ICcXactsDao.java
@@ -0,0 +1,11 @@
+package eu.cloudscale.showcase.db.dao;
+
+import eu.cloudscale.showcase.db.model.ICcXacts;
+
+public interface ICcXactsDao extends IDao<ICcXacts>
+{
+
+ int getLastCcXactsId();
+
+ public ICcXacts findById(Integer id);
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/ICountryDao.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/ICountryDao.java
new file mode 100644
index 0000000..b3cb8f2
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/ICountryDao.java
@@ -0,0 +1,14 @@
+package eu.cloudscale.showcase.db.dao;
+
+import eu.cloudscale.showcase.db.model.ICountry;
+
+public interface ICountryDao extends IDao<ICountry>
+{
+
+ public ICountry findById(int id);
+
+ public ICountry getByName(String country);
+
+ public void createTable();
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/ICustomerDao.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/ICustomerDao.java
new file mode 100644
index 0000000..ebf0fe2
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/ICustomerDao.java
@@ -0,0 +1,20 @@
+package eu.cloudscale.showcase.db.dao;
+
+import java.util.List;
+
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.ICustomer;
+
+
+public interface ICustomerDao extends IDao<ICustomer>
+{
+
+ public ICustomer findById(Integer id);
+
+ public ICustomer getUserBy(String username, String password);
+
+ public List<ICustomer> findByAddress(IAddress addrId);
+
+
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IDao.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IDao.java
new file mode 100644
index 0000000..91fc996
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IDao.java
@@ -0,0 +1,12 @@
+package eu.cloudscale.showcase.db.dao;
+
+
+public interface IDao<T>
+{
+ public T shrani(T object);
+
+ public void finish();
+
+ public T getObject();
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IItemDao.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IItemDao.java
new file mode 100644
index 0000000..9aadafb
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IItemDao.java
@@ -0,0 +1,21 @@
+package eu.cloudscale.showcase.db.dao;
+
+import java.util.List;
+
+import eu.cloudscale.showcase.db.model.IAuthor;
+import eu.cloudscale.showcase.db.model.IItem;
+
+
+public interface IItemDao extends IDao<IItem>
+{
+ public List<IItem> findAll();
+ public IItem findById(int id);
+ public List<IItem> getPromotional();
+ public List<IItem> getNewProducts(String category);
+ public List<Object[]> getBestSellers(String category);
+ public IItem getRandomItem();
+ public IItem getObject();
+ public List<IItem> findAllByAuthor(IAuthor author);
+ public List<IItem> findAllByTitle(String keyword);
+ public List<IItem> findAllBySubject(String keyword);
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IOrderLineDao.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IOrderLineDao.java
new file mode 100644
index 0000000..103be77
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IOrderLineDao.java
@@ -0,0 +1,13 @@
+package eu.cloudscale.showcase.db.dao;
+
+import java.util.List;
+
+import eu.cloudscale.showcase.db.model.IOrderLine;
+import eu.cloudscale.showcase.db.model.IOrders;
+
+public interface IOrderLineDao extends IDao<IOrderLine>
+{
+
+ List<IOrderLine> findAllByOrder(IOrders orders);
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IOrdersDao.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IOrdersDao.java
new file mode 100644
index 0000000..e397e3c
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IOrdersDao.java
@@ -0,0 +1,11 @@
+package eu.cloudscale.showcase.db.dao;
+
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.model.IOrders;
+
+public interface IOrdersDao extends IDao<IOrders>
+{
+ public IOrders getMostRecentOrder(ICustomer customer);
+
+ public IOrders findById(Integer cxOId);
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IShoppingCartDao.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IShoppingCartDao.java
new file mode 100644
index 0000000..f2840a4
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IShoppingCartDao.java
@@ -0,0 +1,16 @@
+package eu.cloudscale.showcase.db.dao;
+
+import java.util.List;
+
+import eu.cloudscale.showcase.db.model.IShoppingCart;
+import eu.cloudscale.showcase.db.model.IShoppingCartLine;
+
+
+public interface IShoppingCartDao extends IDao<IShoppingCart>
+{
+ public Integer createEmptyCart();
+
+ public IShoppingCart findById(Integer shoppingId);
+
+ public List<IShoppingCartLine> findAllBySC(IShoppingCart shoppingCart);
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IShoppingCartLineDao.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IShoppingCartLineDao.java
new file mode 100644
index 0000000..4822a6e
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/IShoppingCartLineDao.java
@@ -0,0 +1,18 @@
+package eu.cloudscale.showcase.db.dao;
+
+import java.util.List;
+
+import eu.cloudscale.showcase.db.model.IShoppingCartLine;
+
+public interface IShoppingCartLineDao extends IDao<IShoppingCartLine>
+{
+
+ public IShoppingCartLine getBySCandItem(Integer shoppingId, int itemId);
+
+ public void delete(IShoppingCartLine bySCandItem);
+
+ public boolean isCartEmpty(int scId);
+
+ public List<Object[]> findBySCId(Integer shoppingId);
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/AddressDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/AddressDaoImpl.java
new file mode 100644
index 0000000..eb964ea
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/AddressDaoImpl.java
@@ -0,0 +1,74 @@
+package eu.cloudscale.showcase.db.dao.mongo.impl;
+
+import java.util.List;
+
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Repository;
+
+import eu.cloudscale.showcase.db.common.ContextHelper;
+import eu.cloudscale.showcase.db.dao.IAddressDao;
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.mongo.Address;
+
+@Repository("mongoAddressDao")
+public class AddressDaoImpl extends DaoImpl<IAddress> implements IAddressDao
+{
+
+// @Autowired
+// private MongoTemplate mongoOps;
+
+ public AddressDaoImpl()
+ {
+ super( (MongoTemplate) ContextHelper.getApplicationContext().getBean( "mongoTemplate" ) );
+
+ }
+
+// public AddressDaoImpl(MongoTemplate mongoOps)
+// {
+// super( mongoOps );
+// }
+
+ @Override
+ public List<IAddress> findAll()
+ {
+ return (List<IAddress>) mongoOps.findAll( IAddress.class, "address" );
+ }
+
+ @Override
+ public IAddress findById(int id)
+ {
+ return (IAddress) mongoOps.findOne( Query.query( Criteria.where( "addrId" ).is( id )), Address.class );
+ }
+
+ @Override
+ public IAddress getObject()
+ {
+ return new Address();
+ }
+
+ @Override
+ public IAddress shrani(IAddress object)
+ {
+ if( object.getAddrId() == null)
+ {
+ object.setAddrId( getLastId() + 1 );
+ }
+ return super.shrani( object );
+ }
+
+ @Override
+ public Integer getLastId()
+ {
+ Sort sort = new Sort(Sort.Direction.DESC, "addrId" );
+
+ IAddress a = mongoOps.findOne(Query.query( new Criteria() ).with( sort ).limit( 1 ), Address.class);
+
+ if( a == null || a.getAddrId() == null)
+ return 0;
+
+ return a.getAddrId();
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/AuthorDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/AuthorDaoImpl.java
new file mode 100644
index 0000000..814028c
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/AuthorDaoImpl.java
@@ -0,0 +1,82 @@
+package eu.cloudscale.showcase.db.dao.mongo.impl;
+
+import java.util.List;
+
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Repository;
+
+import eu.cloudscale.showcase.db.common.ContextHelper;
+import eu.cloudscale.showcase.db.common.Soundex;
+import eu.cloudscale.showcase.db.dao.IAuthorDao;
+import eu.cloudscale.showcase.db.model.IAuthor;
+import eu.cloudscale.showcase.db.model.mongo.Author;
+
+@Repository("mongoAuthorDao")
+public class AuthorDaoImpl extends DaoImpl<IAuthor> implements IAuthorDao
+{
+ public AuthorDaoImpl()
+ {
+ super( (MongoTemplate) ContextHelper.getApplicationContext().getBean( "mongoTemplate" ) );
+ }
+
+// public AuthorDaoImpl(MongoTemplate mongoOps)
+// {
+// super( mongoOps );
+// }
+
+ @SuppressWarnings( {"unchecked", "rawtypes" } )
+ @Override
+ public List<IAuthor> findAll()
+ {
+ List authors = mongoOps.findAll( Author.class, "author" );
+ return (List<IAuthor>) authors;
+ }
+
+ @Override
+ public IAuthor findById(int id)
+ {
+ return (IAuthor) mongoOps.findOne( Query.query( Criteria.where( "authorId" ).is( id ) ), Author.class);
+ }
+
+ @Override
+ public IAuthor getObject()
+ {
+ return new Author();
+ }
+
+ @Override
+ public Integer getLastId()
+ {
+ Sort sort = new Sort(Sort.Direction.DESC, "authorId" );
+
+ Author a = mongoOps.findOne(Query.query( new Criteria() ).with( sort ).limit( 1 ), Author.class);
+
+ if( a == null || a.getAId() == null)
+ return 0;
+
+ return a.getAId();
+ }
+
+ @Override
+ public IAuthor shrani(IAuthor object)
+ {
+ if( object.getAId() == null)
+ {
+ object.setAId( getLastId() +1 );
+ }
+
+ return super.shrani( object );
+ }
+
+ @SuppressWarnings( {"rawtypes", "unchecked" } )
+ @Override
+ public List<IAuthor> findBySoundexLname(String keyword)
+ {
+ List res = mongoOps.find( Query.query( Criteria.where( "lNameSoundex" ).is( Soundex.soundex( keyword ) ) ).limit( 50 ), Author.class );
+
+ return res;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/CcXactsDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/CcXactsDaoImpl.java
new file mode 100644
index 0000000..c59778a
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/CcXactsDaoImpl.java
@@ -0,0 +1,78 @@
+package eu.cloudscale.showcase.db.dao.mongo.impl;
+
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Repository;
+
+import eu.cloudscale.showcase.db.common.ContextHelper;
+import eu.cloudscale.showcase.db.dao.ICcXactsDao;
+import eu.cloudscale.showcase.db.model.ICcXacts;
+import eu.cloudscale.showcase.db.model.mongo.CcXacts;
+
+@Repository("mongoCcXactsDao")
+public class CcXactsDaoImpl extends DaoImpl<ICcXacts> implements ICcXactsDao
+{
+ public CcXactsDaoImpl()
+ {
+ super( (MongoTemplate) ContextHelper.getApplicationContext().getBean( "mongoTemplate" ) );
+ }
+
+// public CcXactsDaoImpl(MongoTemplate mongoOps)
+// {
+// super( mongoOps );
+// }
+
+ @Override
+ public ICcXacts getObject()
+ {
+ return new CcXacts();
+ }
+
+ @Override
+ public ICcXacts findById(Integer id)
+ {
+ return (ICcXacts) mongoOps.findOne( Query.query(Criteria.where( "ccXactsId" ).is( id )), CcXacts.class);
+ }
+
+
+ @Override
+ public int getLastCcXactsId()
+ {
+ Sort sort = new Sort(Sort.Direction.DESC, "ccXactsId" );
+
+ ICcXacts cc = mongoOps.findOne( Query.query(new Criteria()).with( sort ), CcXacts.class);
+
+
+ if( cc == null || cc.getId() == null)
+ return 0;
+
+ return cc.getId();
+ }
+
+ @Override
+ public Integer getLastId()
+ {
+ Sort sort = new Sort(Sort.Direction.DESC, "ccXactsId" );
+
+ CcXacts o = mongoOps.findOne(Query.query( new Criteria() ).with( sort ).limit( 1 ), CcXacts.class);
+
+ if( o == null || o.getId() == null)
+ return 0;
+
+ return o.getId();
+ }
+
+ @Override
+ public ICcXacts shrani(ICcXacts object)
+ {
+ if( object.getId() == null)
+ {
+ object.setId( getLastId() +1 );
+ }
+
+ return super.shrani( object );
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/CountryDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/CountryDaoImpl.java
new file mode 100644
index 0000000..ab53e53
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/CountryDaoImpl.java
@@ -0,0 +1,68 @@
+package eu.cloudscale.showcase.db.dao.mongo.impl;
+
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Repository;
+
+import eu.cloudscale.showcase.db.common.ContextHelper;
+import eu.cloudscale.showcase.db.dao.ICountryDao;
+import eu.cloudscale.showcase.db.model.ICountry;
+import eu.cloudscale.showcase.db.model.mongo.Country;
+
+@Repository("mongoCountryDao")
+public class CountryDaoImpl extends DaoImpl<ICountry> implements ICountryDao
+{
+ public CountryDaoImpl()
+ {
+ super( (MongoTemplate) ContextHelper.getApplicationContext().getBean( "mongoTemplate" ) );
+ }
+
+ @Override
+ public ICountry findById(int id)
+ {
+ return mongoOps.findOne( Query.query( Criteria.where( "coId" ).is(id) ), Country.class );
+ }
+
+ @Override
+ public ICountry getByName(String country)
+ {
+ return mongoOps.findOne( Query.query( Criteria.where( "coName" ).regex(country, "i")), Country.class );
+ }
+
+ @Override
+ public ICountry getObject()
+ {
+ return new Country();
+ }
+
+ @Override
+ public Integer getLastId()
+ {
+ Sort sort = new Sort(Sort.Direction.DESC, "coId" );
+
+ Country o = mongoOps.findOne(Query.query( new Criteria() ).with( sort ).limit( 1 ), Country.class);
+
+ if( o == null || o.getCoId() == null)
+ return 0;
+
+ return o.getCoId();
+ }
+
+ @Override
+ public ICountry shrani(ICountry object)
+ {
+ if( object.getCoId() == null)
+ {
+ object.setCoId( getLastId() +1 );
+ }
+
+ return super.shrani( object );
+ }
+
+ @Override
+ public void createTable()
+ {
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/CustomerDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/CustomerDaoImpl.java
new file mode 100644
index 0000000..e873566
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/CustomerDaoImpl.java
@@ -0,0 +1,80 @@
+package eu.cloudscale.showcase.db.dao.mongo.impl;
+
+import java.util.List;
+
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Repository;
+
+import eu.cloudscale.showcase.db.common.ContextHelper;
+import eu.cloudscale.showcase.db.dao.ICustomerDao;
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.model.mongo.Customer;
+
+@Repository("mongoCustomerDao")
+public class CustomerDaoImpl extends DaoImpl<ICustomer> implements ICustomerDao
+{
+ public CustomerDaoImpl()
+ {
+ super( (MongoTemplate) ContextHelper.getApplicationContext().getBean( "mongoTemplate" ) );
+ }
+
+// public CustomerDaoImpl(MongoTemplate mongoOps)
+// {
+// super( mongoOps );
+// }
+
+ @Override
+ public ICustomer findById(Integer id)
+ {
+ return mongoOps.findOne( Query.query(Criteria.where( "CId" ).is( id )), Customer.class);
+ }
+
+ @Override
+ public ICustomer getUserBy(String username, String password)
+ {
+ return mongoOps.findOne( Query.query( Criteria.where( "CUname" ).is( username.toLowerCase()).and( "CPasswd" ).is(password.toLowerCase())), Customer.class );
+ }
+
+ @Override
+ public ICustomer getObject()
+ {
+ return new Customer();
+ }
+
+ @SuppressWarnings( {"unchecked", "rawtypes" } )
+ @Override
+ public List<ICustomer> findByAddress(IAddress address)
+ {
+ List res = mongoOps.find( Query.query(Criteria.where( "addrId" ).is( address.getAddrId() )), Customer.class );
+
+ return res;
+ }
+
+ @Override
+ public Integer getLastId()
+ {
+ Sort sort = new Sort(Sort.Direction.DESC, "cId" );
+
+ Customer c = mongoOps.findOne(Query.query( new Criteria() ).with( sort ).limit( 1 ), Customer.class);
+
+ if( c == null || c.getCId() == null)
+ return 0;
+
+ return c.getCId();
+ }
+
+ @Override
+ public ICustomer shrani(ICustomer object)
+ {
+ if( object.getCId() == null)
+ {
+ object.setCId( getLastId() +1 );
+ }
+
+ return super.shrani( object );
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/DaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/DaoImpl.java
new file mode 100644
index 0000000..3f75394
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/DaoImpl.java
@@ -0,0 +1,48 @@
+package eu.cloudscale.showcase.db.dao.mongo.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.transaction.annotation.Transactional;
+
+public abstract class DaoImpl<T> implements IDaoExt<T>
+{
+ @Autowired
+ protected MongoTemplate mongoOps;
+
+ public DaoImpl()
+ {
+ }
+
+ public DaoImpl(MongoTemplate mongoOps)
+ {
+ this.mongoOps = mongoOps;
+ }
+
+ @Override
+ @Transactional(readOnly=false)
+ public T shrani(T object)
+ {
+ mongoOps.save( object );
+ return object;
+ }
+
+ @Override
+ public void finish()
+ {
+ }
+
+ @Override
+ public T getObject()
+ {
+ try
+ {
+ throw new UnsupportedOperationException( "Implement in DAO implementation!" );
+ }
+ catch ( UnsupportedOperationException e )
+ {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/IDaoExt.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/IDaoExt.java
new file mode 100644
index 0000000..24b2e4d
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/IDaoExt.java
@@ -0,0 +1,10 @@
+package eu.cloudscale.showcase.db.dao.mongo.impl;
+
+import eu.cloudscale.showcase.db.dao.IDao;
+
+
+public interface IDaoExt<T> extends IDao<T>
+{
+ public Integer getLastId();
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/ItemDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/ItemDaoImpl.java
new file mode 100644
index 0000000..df7914b
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/ItemDaoImpl.java
@@ -0,0 +1,232 @@
+package eu.cloudscale.showcase.db.dao.mongo.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Repository;
+
+import eu.cloudscale.showcase.db.common.ContextHelper;
+import eu.cloudscale.showcase.db.common.Soundex;
+import eu.cloudscale.showcase.db.dao.IItemDao;
+import eu.cloudscale.showcase.db.model.IAuthor;
+import eu.cloudscale.showcase.db.model.IItem;
+import eu.cloudscale.showcase.db.model.mongo.Item;
+
+@Repository("mongoItemDao")
+public class ItemDaoImpl extends DaoImpl<IItem> implements IItemDao
+{
+ public ItemDaoImpl()
+ {
+ super( (MongoTemplate) ContextHelper.getApplicationContext().getBean( "mongoTemplate" ) );
+ }
+
+ @SuppressWarnings( {"rawtypes", "unchecked" } )
+ @Override
+ public List<IItem> findAll()
+ {
+ List items = mongoOps.find( Query.query(new Criteria()).limit( 50 ), Item.class, "item");
+ return (List<IItem>) items;
+ }
+
+ @Override
+ public IItem findById(int id)
+ {
+ Item item = mongoOps.findOne( Query.query( Criteria.where( "IId" ).is( id ) ), Item.class);
+ return item;
+ }
+
+ @Override
+ public IItem getRandomItem()
+ {
+ return (IItem) mongoOps.findOne( Query.query( Criteria.where( "IRandom" ).gt( new Random().nextDouble() )), Item.class, "item" );
+ }
+
+ @Override
+ public List<IItem> getPromotional()
+ {
+
+ IItem item = getRandomItem();
+ ArrayList<IItem> promotional = new ArrayList<IItem>();
+
+ promotional.add( findById( item.getIRelated1()));
+
+ promotional.add(findById( item.getIRelated2()));
+
+ promotional.add(findById( item.getIRelated3()));
+
+ promotional.add(findById( item.getIRelated4()));
+
+ promotional.add(findById( item.getIRelated5()));
+
+ return promotional;
+ }
+
+ @SuppressWarnings( {"rawtypes", "unchecked" } )
+ @Override
+ public List<IItem> getNewProducts(String category)
+ {
+ Sort sort = new Sort(Sort.Direction.DESC, "IPubDate").and( new Sort(Sort.Direction.ASC, "ITitle") );
+ List items = mongoOps.find( Query.query(Criteria.where( "ISubject" ).is(category) ).with( sort ).limit( 50 ), Item.class );
+ return (List<IItem>) items;
+ }
+
+ class ValueObject
+ {
+ private String id;
+ private float value;
+
+ public String getId()
+ {
+ return id;
+ }
+
+ public void setId(String id)
+ {
+ this.id = id;
+ }
+
+ public float getValue()
+ {
+ return value;
+ }
+
+ public void setValue(float value)
+ {
+ this.value = value;
+ }
+
+ }
+
+ @Override
+ public List<Object[]> getBestSellers(String category)
+ {
+ Sort sort = new Sort( Sort.Direction.DESC, "olQty" );
+
+ List<Item> res = mongoOps.find( Query.query(Criteria.where( "ISubject" ).is( category )).limit( 50 ).with( sort ), Item.class);
+
+ ArrayList<Object[]> items = new ArrayList<Object[]>();
+ for( Item item : res)
+ {
+ Object[] itemObj = new Object[5];
+ itemObj[0] = item.getIId();
+ itemObj[1] = item.getITitle();
+ itemObj[2] = item.getAuthor().getAFname();
+ itemObj[3] = item.getAuthor().getALname();
+ itemObj[4] = item.getOlQty();
+
+ items.add( itemObj );
+ }
+
+ return items;
+
+// BasicDBObject groupFields = new BasicDBObject("_id", "$itemId");
+// groupFields.put( "qty", new BasicDBObject("$sum", "$olQty") );
+//
+// BasicDBObject group = new BasicDBObject("$group", groupFields);
+//
+// BasicDBObject limit = new BasicDBObject("$limit", 3333);
+//
+// BasicDBObject sort = new BasicDBObject("$sort", new BasicDBObject("qty", -1));
+//
+// AggregationOutput output = mongoOps.getCollection( mongoOps.getCollectionName( OrderLine.class ) ).aggregate( group, sort, limit );
+//
+// IItemDao itemDao = DatabaseHelper.getDatabase().getItemDaoImpl();
+// ArrayList<Object[]> items = new ArrayList<Object[]>();
+//
+// for( DBObject object : output.results() )
+// {
+// if( items.size() == 50 )
+// {
+// break;
+// }
+//
+// IItem item = itemDao.findById( (Integer) object.get( "_id" ) );
+//
+// if(item.getISubject().equals( category ))
+// {
+// Object[] itemObj = new Object[5];
+// itemObj[0] = item.getIId();
+// itemObj[1] = item.getITitle();
+// itemObj[2] = item.getAuthor().getAFname();
+// itemObj[3] = item.getAuthor().getALname();
+// itemObj[4] = object.get( "qty" );
+// items.add( itemObj );
+// }
+//
+//
+// }
+//
+// return items;
+// DELA FUL POCAS!!! - glej http://stackoverflow.com/questions/4430407/mongodb-mapreduce-is-much-slower-than-pure-java-processing
+// String mapFunction = "function()" +
+// "{" +
+// " emit(this.itemId, this.olQty)" +
+// "}";
+// String reduceFunction = "function(k, v)" +
+// "{" +
+// " return Array.sum(v)" +
+// "}";
+// MapReduceResults<ValueObject> results = mongoOps.mapReduce( "orderLine", mapFunction, reduceFunction, ValueObject.class );
+ }
+
+ @Override
+ public IItem getObject()
+ {
+ return new Item();
+ }
+
+ @Override
+ public Integer getLastId()
+ {
+ Sort sort = new Sort(Sort.Direction.DESC, "iId" );
+
+ Item o = mongoOps.findOne(Query.query( new Criteria() ).with( sort ).limit( 1 ), Item.class);
+
+ if( o == null || o.getIId() == null)
+ return 0;
+
+ return o.getIId();
+ }
+
+ @Override
+ public IItem shrani(IItem object)
+ {
+ if( object.getIId() == null)
+ {
+ object.setIId( getLastId() +1 );
+ }
+
+ return super.shrani( object );
+ }
+
+ @SuppressWarnings( {"rawtypes", "unchecked" } )
+ @Override
+ public List<IItem> findAllByAuthor(IAuthor author)
+ {
+ List res = mongoOps.find( Query.query( Criteria.where( "authId" ).is( author.getAId() ) ).limit( 50 ), Item.class );
+ return res;
+ }
+
+ @SuppressWarnings( {"rawtypes", "unchecked" } )
+ @Override
+ public List<IItem> findAllByTitle(String keyword)
+ {
+ List res = mongoOps.find( Query.query( Criteria.where( "iTitleSoundex" ).is( Soundex.soundex( keyword ) ) ).limit( 50 ), Item.class );
+
+ return res;
+ }
+
+ @SuppressWarnings( {"rawtypes", "unchecked" } )
+ @Override
+ public List<IItem> findAllBySubject(String keyword)
+ {
+ List res = mongoOps.find( Query.query( Criteria.where( "iSubject" ).is( keyword )).limit( 50 ), Item.class );
+
+ return res;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/OrderLineDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/OrderLineDaoImpl.java
new file mode 100644
index 0000000..39691c2
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/OrderLineDaoImpl.java
@@ -0,0 +1,63 @@
+package eu.cloudscale.showcase.db.dao.mongo.impl;
+
+import java.util.List;
+
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Repository;
+
+import eu.cloudscale.showcase.db.common.ContextHelper;
+import eu.cloudscale.showcase.db.dao.IOrderLineDao;
+import eu.cloudscale.showcase.db.model.IOrderLine;
+import eu.cloudscale.showcase.db.model.IOrders;
+import eu.cloudscale.showcase.db.model.mongo.OrderLine;
+
+@Repository("mongoOrderLineDao")
+public class OrderLineDaoImpl extends DaoImpl<IOrderLine> implements IOrderLineDao
+{
+
+ public OrderLineDaoImpl()
+ {
+ super( (MongoTemplate) ContextHelper.getApplicationContext().getBean( "mongoTemplate" ) );
+ }
+
+ @Override
+ public IOrderLine getObject()
+ {
+ return new OrderLine();
+ }
+
+ @SuppressWarnings( {"unchecked", "rawtypes" } )
+ @Override
+ public List<IOrderLine> findAllByOrder(IOrders orders)
+ {
+ List res = mongoOps.find( Query.query( Criteria.where( "orderId" ).is( orders.getOId() )), OrderLine.class );
+ return res;
+ }
+
+ @Override
+ public Integer getLastId()
+ {
+ Sort sort = new Sort(Sort.Direction.DESC, "olId" );
+
+ OrderLine o = mongoOps.findOne(Query.query( new Criteria() ).with( sort ).limit( 1 ), OrderLine.class);
+
+ if( o == null || o.getOlId() == null)
+ return 0;
+
+ return o.getOlId();
+ }
+
+ @Override
+ public IOrderLine shrani(IOrderLine object)
+ {
+ if( object.getOlId() == null)
+ {
+ object.setOlId( getLastId() +1 );
+ }
+
+ return super.shrani( object );
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/OrdersDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/OrdersDaoImpl.java
new file mode 100644
index 0000000..9955db5
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/OrdersDaoImpl.java
@@ -0,0 +1,71 @@
+package eu.cloudscale.showcase.db.dao.mongo.impl;
+
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Repository;
+
+import eu.cloudscale.showcase.db.common.ContextHelper;
+import eu.cloudscale.showcase.db.dao.IOrdersDao;
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.model.IOrders;
+import eu.cloudscale.showcase.db.model.mongo.Customer;
+import eu.cloudscale.showcase.db.model.mongo.Orders;
+
+@Repository("mongoOrdersDao")
+public class OrdersDaoImpl extends DaoImpl<IOrders> implements IOrdersDao
+{
+
+ public OrdersDaoImpl()
+ {
+ super( (MongoTemplate) ContextHelper.getApplicationContext().getBean( "mongoTemplate" ) );
+ }
+
+ @Override
+ public IOrders getMostRecentOrder(ICustomer customer)
+ {
+
+ Sort sort = new Sort( Sort.Direction.DESC, "ODate" );
+ Orders order = mongoOps.findOne( Query.query(Criteria.where( "customer" ).is(customer.getCId())).with( sort ), Orders.class );
+
+ return order;
+ }
+
+ @Override
+ public IOrders getObject()
+ {
+ return new Orders();
+ }
+
+ @Override
+ public IOrders findById(Integer cxOId)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Integer getLastId()
+ {
+ Sort sort = new Sort(Sort.Direction.DESC, "oId" );
+
+ Orders o = mongoOps.findOne(Query.query( new Criteria() ).with( sort ).limit( 1 ), Orders.class);
+
+ if( o == null || o.getOId() == null)
+ return 0;
+
+ return o.getOId();
+ }
+
+ @Override
+ public IOrders shrani(IOrders object)
+ {
+ if( object.getOId() == null)
+ {
+ object.setOId( getLastId() +1 );
+ }
+
+ return super.shrani( object );
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/ShoppingCartDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/ShoppingCartDaoImpl.java
new file mode 100644
index 0000000..b0f59e5
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/ShoppingCartDaoImpl.java
@@ -0,0 +1,81 @@
+package eu.cloudscale.showcase.db.dao.mongo.impl;
+
+import java.util.Date;
+import java.util.List;
+
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Repository;
+
+import eu.cloudscale.showcase.db.common.ContextHelper;
+import eu.cloudscale.showcase.db.dao.IShoppingCartDao;
+import eu.cloudscale.showcase.db.model.IShoppingCart;
+import eu.cloudscale.showcase.db.model.IShoppingCartLine;
+import eu.cloudscale.showcase.db.model.mongo.ShoppingCart;
+import eu.cloudscale.showcase.db.model.mongo.ShoppingCartLine;
+
+@Repository("mongoShoppingCartDao")
+public class ShoppingCartDaoImpl extends DaoImpl<IShoppingCart> implements IShoppingCartDao
+{
+ public ShoppingCartDaoImpl()
+ {
+ super( (MongoTemplate) ContextHelper.getApplicationContext().getBean( "mongoTemplate" ) );
+ }
+
+ @Override
+ public Integer createEmptyCart()
+ {
+ IShoppingCart sc = new ShoppingCart();
+ sc.setScId( getLastId() + 1 );
+ sc.setScTime( new Date() );
+ shrani( sc );
+
+ return sc.getScId();
+ }
+
+ @Override
+ public Integer getLastId()
+ {
+ Sort sort = new Sort(Sort.Direction.DESC, "scId" );
+
+ ShoppingCart sc = mongoOps.findOne(Query.query( new Criteria() ).with( sort ).limit( 1 ), ShoppingCart.class);
+
+ if( sc == null || sc.getScId() == null)
+ return 0;
+
+ return sc.getScId();
+ }
+
+ @Override
+ public IShoppingCart findById(Integer shoppingId)
+ {
+ return mongoOps.findOne( Query.query(Criteria.where("scId").is(shoppingId)), ShoppingCart.class );
+ }
+
+ @Override
+ public IShoppingCart getObject()
+ {
+ return new ShoppingCart();
+ }
+
+ @SuppressWarnings( {"unchecked", "rawtypes" } )
+ @Override
+ public List<IShoppingCartLine> findAllBySC(IShoppingCart shoppingCart)
+ {
+ List res = mongoOps.find( Query.query(Criteria.where( "shoppingCart" ).is( shoppingCart.getScId() )), ShoppingCartLine.class );
+ return res;
+ }
+
+ @Override
+ public IShoppingCart shrani(IShoppingCart object)
+ {
+ if( object.getScId() == null )
+ {
+ object.setScId( getLastId()+1 );
+ }
+ return super.shrani( object );
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/ShoppingCartLineDaoImpl.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/ShoppingCartLineDaoImpl.java
new file mode 100644
index 0000000..3d9de2b
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/dao/mongo/impl/ShoppingCartLineDaoImpl.java
@@ -0,0 +1,87 @@
+package eu.cloudscale.showcase.db.dao.mongo.impl;
+
+import java.util.List;
+
+import org.springframework.data.domain.Sort;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.stereotype.Repository;
+
+import eu.cloudscale.showcase.db.common.ContextHelper;
+import eu.cloudscale.showcase.db.dao.IShoppingCartLineDao;
+import eu.cloudscale.showcase.db.model.IShoppingCartLine;
+import eu.cloudscale.showcase.db.model.mongo.ShoppingCartLine;
+
+@Repository("mongoShoppingCartLineDao")
+public class ShoppingCartLineDaoImpl extends DaoImpl<IShoppingCartLine> implements IShoppingCartLineDao
+{
+ public ShoppingCartLineDaoImpl()
+ {
+ super( (MongoTemplate) ContextHelper.getApplicationContext().getBean( "mongoTemplate" ) );
+ }
+
+// public ShoppingCartLineDaoImpl(MongoTemplate mongoOps)
+// {
+// super(mongoOps);
+// }
+
+ @Override
+ public IShoppingCartLine getBySCandItem(Integer shoppingId, int itemId)
+ {
+ IShoppingCartLine scl = mongoOps.findOne( Query.query( Criteria.where( "shoppingCart" ).is( shoppingId ).andOperator( Criteria.where( "item" ).is( itemId ) )), ShoppingCartLine.class );
+
+ return scl;
+ }
+
+ @Override
+ public void delete(IShoppingCartLine bySCandItem)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean isCartEmpty(int scId)
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public List<Object[]> findBySCId(Integer shoppingId)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public IShoppingCartLine getObject()
+ {
+ return new ShoppingCartLine();
+ }
+
+ @Override
+ public Integer getLastId()
+ {
+ Sort sort = new Sort(Sort.Direction.DESC, "sclId" );
+
+ ShoppingCartLine scl = mongoOps.findOne(Query.query( new Criteria() ).with( sort ).limit( 1 ), ShoppingCartLine.class);
+
+ if( scl == null || scl.getSclId() == null)
+ return 0;
+
+ return scl.getSclId();
+ }
+
+ @Override
+ public IShoppingCartLine shrani(IShoppingCartLine object)
+ {
+ if( object.getSclId() == null )
+ {
+ object.setSclId( getLastId() + 1 );
+ }
+ return super.shrani( object );
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/IDao.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/IDao.java
new file mode 100644
index 0000000..a09a0fb
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/IDao.java
@@ -0,0 +1,25 @@
+package eu.cloudscale.showcase.db;
+
+import eu.cloudscale.showcase.db.dao.IAddressDao;
+import eu.cloudscale.showcase.db.dao.ICustomerDao;
+import eu.cloudscale.showcase.db.dao.IItemDao;
+import eu.cloudscale.showcase.db.dao.IShoppingCartDao;
+import eu.cloudscale.showcase.db.dao.IShoppingCartLineDao;
+
+
+public interface IDao
+{
+
+ public IItemDao getItemDao();
+
+ public IShoppingCartLineDao getShoppingCartLineDao();
+
+ public IShoppingCartDao getShoppingCartDao();
+
+ public IAddressDao getAddressDao();
+
+ public ICustomerDao getCustomerDao();
+
+ public IShoppingCartLineDao getShoppingCartLineDaoImpl();
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/IDaos.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/IDaos.java
new file mode 100644
index 0000000..7eac450
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/IDaos.java
@@ -0,0 +1,37 @@
+package eu.cloudscale.showcase.db;
+
+import eu.cloudscale.showcase.db.dao.IAddressDao;
+import eu.cloudscale.showcase.db.dao.IAuthorDao;
+import eu.cloudscale.showcase.db.dao.ICcXactsDao;
+import eu.cloudscale.showcase.db.dao.ICountryDao;
+import eu.cloudscale.showcase.db.dao.ICustomerDao;
+import eu.cloudscale.showcase.db.dao.IItemDao;
+import eu.cloudscale.showcase.db.dao.IOrderLineDao;
+import eu.cloudscale.showcase.db.dao.IOrdersDao;
+import eu.cloudscale.showcase.db.dao.IShoppingCartDao;
+import eu.cloudscale.showcase.db.dao.IShoppingCartLineDao;
+
+
+public interface IDaos
+{
+ public IAddressDao getAddressDaoImpl();
+
+ public IAuthorDao getAuthorDaoImpl();
+
+ public ICcXactsDao getCcXactsDaoImpl();
+
+ public ICountryDao getCountryDaoImpl();
+
+ public ICustomerDao getCustomerDaoImpl();
+
+ public IItemDao getItemDaoImpl();
+
+ public IOrderLineDao getOrderLineDaoImpl();
+
+ public IOrdersDao getOrdersDaoImpl();
+
+ public IShoppingCartLineDao getShoppingCartLineDaoImpl();
+
+ public IShoppingCartDao getShoppingCartDaoImpl();
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/IService.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/IService.java
new file mode 100644
index 0000000..ecdecc1
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/IService.java
@@ -0,0 +1,37 @@
+package eu.cloudscale.showcase.db;
+
+import java.util.Date;
+import java.util.List;
+
+import eu.cloudscale.showcase.db.dao.ICustomerDao;
+import eu.cloudscale.showcase.db.model.IItem;
+import eu.cloudscale.showcase.db.model.IShoppingCart;
+
+public interface IService extends IDaos
+{
+
+ public List getNewProducts(String category);
+
+ public IShoppingCart doCart(Integer shoppingId, Integer itemId,
+ List<Integer> ids, List<Integer> quantities);
+
+ public BuyConfirmResult doBuyConfirm(Integer shoppingId, Integer customerId,
+ String ccType, long ccNumber, String ccName, Date ccExpiry,
+ String shipping, String street1, String street2, String city,
+ String state, String zip, String country);
+
+ public BuyConfirmResult doBuyConfirm(Integer shoppingId, Integer customerId,
+ String ccType, Long ccNumber, String ccName, Date ccExpiry,
+ String shipping);
+
+ public ICustomerDao getCustomerDaoImpl();
+
+ public List<IItem> searchByAuthor(String keyword);
+
+ public List<IItem> searchByTitle(String keyword);
+
+ public List<IItem> searchBySubject(String keyword);
+
+ public List<Object[]> getBestSellers(String category);
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Address.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Address.java
new file mode 100644
index 0000000..cdb4a78
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Address.java
@@ -0,0 +1,183 @@
+package eu.cloudscale.showcase.db.model.hibernate;
+
+// Generated May 16, 2013 3:07:18 PM by Hibernate Tools 4.0.0
+
+import static javax.persistence.GenerationType.IDENTITY;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.ICountry;
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.model.IOrders;
+
+/**
+ * Address generated by hbm2java
+ */
+@Entity
+@Table( name = "address", catalog = "tpcw" )
+public class Address implements IAddress
+{
+
+ private Integer addrId;
+
+ private ICountry country;
+
+ private String addrStreet1;
+
+ private String addrStreet2;
+
+ private String addrCity;
+
+ private String addrState;
+
+ private String addrZip;
+
+ private Set<IOrders> ordersesForOBillAddrId = new HashSet<IOrders>( 0 );
+
+ private Set<IOrders> ordersesForOShipAddrId = new HashSet<IOrders>( 0 );
+
+ private Set<ICustomer> customers = new HashSet<ICustomer>( 0 );
+
+ public Address()
+ {
+ }
+
+ @Id
+ @GeneratedValue( strategy = IDENTITY )
+ @Column( name = "ADDR_ID", unique = true, nullable = false )
+ @Override
+ public Integer getAddrId()
+ {
+ return this.addrId;
+ }
+
+ public void setAddrId(Integer addrId)
+ {
+ this.addrId = addrId;
+ }
+
+ @ManyToOne( targetEntity=Country.class, fetch = FetchType.EAGER )
+ @JoinColumn( name = "ADDR_CO_ID", nullable = false )
+ @Override
+ public ICountry getCountry()
+ {
+ return this.country;
+ }
+
+ @Override
+ public void setCountry(ICountry country)
+ {
+ this.country = (Country) country;
+ }
+
+ @Column( name = "ADDR_STREET1", length = 40 )
+ @Override
+ public String getAddrStreet1()
+ {
+ return this.addrStreet1;
+ }
+
+ @Override
+ public void setAddrStreet1(String addrStreet1)
+ {
+ this.addrStreet1 = addrStreet1;
+ }
+
+ @Column( name = "ADDR_STREET2", length = 40 )
+ @Override
+ public String getAddrStreet2()
+ {
+ return this.addrStreet2;
+ }
+
+ @Override
+ public void setAddrStreet2(String addrStreet2)
+ {
+ this.addrStreet2 = addrStreet2;
+ }
+
+ @Column( name = "ADDR_CITY", length = 30 )
+ @Override
+ public String getAddrCity()
+ {
+ return this.addrCity;
+ }
+
+ @Override
+ public void setAddrCity(String addrCity)
+ {
+ this.addrCity = addrCity;
+ }
+
+ @Column( name = "ADDR_STATE", length = 20 )
+ @Override
+ public String getAddrState()
+ {
+ return this.addrState;
+ }
+
+ @Override
+ public void setAddrState(String addrState)
+ {
+ this.addrState = addrState;
+ }
+
+ @Column( name = "ADDR_ZIP", length = 10 )
+ @Override
+ public String getAddrZip()
+ {
+ return this.addrZip;
+ }
+
+ @Override
+ public void setAddrZip(String addrZip)
+ {
+ this.addrZip = addrZip;
+ }
+
+ @OneToMany( targetEntity=Orders.class, fetch = FetchType.LAZY, mappedBy = "addressByOBillAddrId" )
+ public Set<IOrders> getOrdersesForOBillAddrId()
+ {
+ return this.ordersesForOBillAddrId;
+ }
+
+ public void setOrdersesForOBillAddrId(Set<IOrders> ordersesForOBillAddrId)
+ {
+ this.ordersesForOBillAddrId = ordersesForOBillAddrId;
+ }
+
+ @OneToMany( targetEntity=Orders.class, fetch = FetchType.LAZY, mappedBy = "addressByOShipAddrId" )
+ public Set<IOrders> getOrdersesForOShipAddrId()
+ {
+ return this.ordersesForOShipAddrId;
+ }
+
+ public void setOrdersesForOShipAddrId(Set<IOrders> ordersesForOShipAddrId)
+ {
+ this.ordersesForOShipAddrId = ordersesForOShipAddrId;
+ }
+
+ @OneToMany( targetEntity=Customer.class, fetch = FetchType.LAZY, mappedBy = "address" )
+ public Set<ICustomer> getCustomers()
+ {
+ return this.customers;
+ }
+
+ public void setCustomers(Set<ICustomer> customers)
+ {
+ this.customers = customers;
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Author.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Author.java
new file mode 100644
index 0000000..e71e116
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Author.java
@@ -0,0 +1,156 @@
+package eu.cloudscale.showcase.db.model.hibernate;
+
+// Generated May 16, 2013 3:07:18 PM by Hibernate Tools 4.0.0
+
+import static javax.persistence.GenerationType.IDENTITY;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import eu.cloudscale.showcase.db.model.IAuthor;
+import eu.cloudscale.showcase.db.model.IItem;
+
+/**
+ * Author generated by hbm2java
+ */
+@Entity
+@Table( name = "author", catalog = "tpcw" )
+public class Author implements IAuthor, Serializable
+{
+
+ private static final long serialVersionUID = 1L;
+
+ private Integer aId;
+
+ private String AFname;
+
+ private String ALname;
+
+ private String AMname;
+
+ private Date ADob;
+
+ private String ABio;
+
+ private Set<IItem> items = new HashSet<IItem>( 0 );
+
+ public Author()
+ {
+ }
+
+ public Author(String AFname, String ALname, String AMname, Date ADob,
+ String ABio, Set<IItem> items)
+ {
+ this.AFname = AFname;
+ this.ALname = ALname;
+ this.AMname = AMname;
+ this.ADob = ADob;
+ this.ABio = ABio;
+ this.items = items;
+ }
+
+ @Id
+ @GeneratedValue( strategy = IDENTITY )
+ @Column( name = "A_ID", unique = true, nullable = false )
+ @Override
+ public Integer getAId()
+ {
+ return this.aId;
+ }
+
+ @Override
+ public void setAId(Integer AId)
+ {
+ this.aId = AId;
+ }
+
+ @Column( name = "A_FNAME", length = 20 )
+ @Override
+ public String getAFname()
+ {
+ return this.AFname;
+ }
+
+ @Override
+ public void setAFname(String AFname)
+ {
+ this.AFname = AFname;
+ }
+
+ @Column( name = "A_LNAME", length = 20 )
+ @Override
+ public String getALname()
+ {
+ return this.ALname;
+ }
+
+ @Override
+ public void setALname(String ALname)
+ {
+ this.ALname = ALname;
+ }
+
+ @Column( name = "A_MNAME", length = 20 )
+ @Override
+ public String getAMname()
+ {
+ return this.AMname;
+ }
+
+ @Override
+ public void setAMname(String AMname)
+ {
+ this.AMname = AMname;
+ }
+
+ @Temporal( TemporalType.TIMESTAMP )
+ @Column( name = "A_DOB", length = 19 )
+ @Override
+ public Date getADob()
+ {
+ return this.ADob;
+ }
+
+ @Override
+ public void setADob(Date ADob)
+ {
+ this.ADob = ADob;
+ }
+
+ @Column( name = "A_BIO", length = 65535 )
+ @Override
+ public String getABio()
+ {
+ return this.ABio;
+ }
+
+ @Override
+ public void setABio(String ABio)
+ {
+ this.ABio = ABio;
+ }
+
+ @OneToMany( targetEntity=Item.class, fetch = FetchType.LAZY, mappedBy = "author" )
+ public Set<IItem> getItems()
+ {
+ return this.items;
+ }
+
+ public void setItems(Set<IItem> items)
+ {
+ this.items = items;
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/CcXacts.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/CcXacts.java
new file mode 100644
index 0000000..35c0adb
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/CcXacts.java
@@ -0,0 +1,187 @@
+package eu.cloudscale.showcase.db.model.hibernate;
+
+// Generated May 16, 2013 3:07:18 PM by Hibernate Tools 4.0.0
+
+import static javax.persistence.GenerationType.IDENTITY;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+
+import eu.cloudscale.showcase.db.model.IAuthor;
+import eu.cloudscale.showcase.db.model.ICcXacts;
+import eu.cloudscale.showcase.db.model.ICountry;
+import eu.cloudscale.showcase.db.model.IOrders;
+
+/**
+ * CcXacts generated by hbm2java
+ */
+@Entity
+@Table( name = "cc_xacts", catalog = "tpcw" )
+public class CcXacts implements ICcXacts
+{
+
+ private ICountry country;
+
+ private IOrders orders;
+
+ private Integer id;
+
+ private String cxType;
+
+ private Integer cxNum;
+
+ private String cxName;
+
+ private Date cxExpiry;
+
+ private IAuthor cxAuthId;
+
+ private Double cxXactAmt;
+
+ private Date cxXactDate;
+
+ @Id
+ @GeneratedValue( strategy = IDENTITY )
+ @Column( name = "CX_ID", unique = true, nullable = false )
+ @Override
+ public Integer getId()
+ {
+ return this.id;
+ }
+
+ @Override
+ public void setId(Integer string)
+ {
+ this.id = string;
+ }
+
+ @ManyToOne( targetEntity=Orders.class, fetch = FetchType.LAZY )
+ @JoinColumn( name = "CX_O_ID", nullable = false )
+ @Override
+ public IOrders getOrders()
+ {
+ return this.orders;
+ }
+
+ @Override
+ public void setOrders(IOrders orders)
+ {
+ this.orders = orders;
+ }
+
+ @Column( name = "CX_TYPE", length = 10 )
+ @Override
+ public String getCxType()
+ {
+ return this.cxType;
+ }
+
+ @Override
+ public void setCxType(String cxType)
+ {
+ this.cxType = cxType;
+ }
+
+ @Column( name = "CX_NUM" )
+ @Override
+ public Integer getCxNum()
+ {
+ return this.cxNum;
+ }
+
+ @Override
+ public void setCxNum(Integer cxNum)
+ {
+ this.cxNum = cxNum;
+ }
+
+ @Column( name = "CX_NAME", length = 31 )
+ @Override
+ public String getCxName()
+ {
+ return this.cxName;
+ }
+
+ @Override
+ public void setCxName(String cxName)
+ {
+ this.cxName = cxName;
+ }
+
+ @Column( name = "CX_EXPIRY", length = 10 )
+ @Override
+ public Date getCxExpiry()
+ {
+ return this.cxExpiry;
+ }
+
+ @Override
+ public void setCxExpiry(Date cxExpiry)
+ {
+ this.cxExpiry = cxExpiry;
+ }
+
+// @Column( name = "CX_AUTH_ID", length = 15 )
+ @OneToOne( targetEntity=Author.class, fetch=FetchType.EAGER)
+ @JoinColumn( name="CX_AUTH_ID" )
+ @Override
+ public IAuthor getCxAuthId()
+ {
+ return this.cxAuthId;
+ }
+
+ @Override
+ public void setCxAuthId(IAuthor cxAuthId)
+ {
+ this.cxAuthId = cxAuthId;
+ }
+
+ @Column( name = "CX_XACT_AMT", precision = 15 )
+ @Override
+ public Double getCxXactAmt()
+ {
+ return this.cxXactAmt;
+ }
+
+ @Override
+ public void setCxXactAmt(Double o_TOTAL)
+ {
+ this.cxXactAmt = o_TOTAL;
+ }
+
+ @Column( name = "CX_XACT_DATE", length = 19 )
+ @Override
+ public Date getCxXactDate()
+ {
+ return this.cxXactDate;
+ }
+
+ @Override
+ public void setCxXactDate(Date cxXactDate)
+ {
+ this.cxXactDate = cxXactDate;
+ }
+
+ @ManyToOne( targetEntity=Country.class, fetch = FetchType.LAZY )
+ @JoinColumn( name = "CX_CO_ID", nullable = false)
+ @Override
+ public ICountry getCountry()
+ {
+ return this.country;
+ }
+
+ @Override
+ public void setCountry(ICountry country)
+ {
+ this.country = country;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Country.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Country.java
new file mode 100644
index 0000000..d2411ef
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Country.java
@@ -0,0 +1,132 @@
+package eu.cloudscale.showcase.db.model.hibernate;
+
+// Generated May 16, 2013 3:07:18 PM by Hibernate Tools 4.0.0
+
+import static javax.persistence.GenerationType.IDENTITY;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.ICcXacts;
+import eu.cloudscale.showcase.db.model.ICountry;
+
+/**
+ * Country generated by hbm2java
+ */
+@Entity
+@Table( name = "country", catalog = "tpcw" )
+public class Country implements ICountry
+{
+
+ private Integer coId;
+
+ private String coName;
+
+ private Double coExchange;
+
+ private String coCurrency;
+
+ private Set<IAddress> addresses = new HashSet<IAddress>( 0 );
+
+ private Set<ICcXacts> ccXactses = new HashSet<ICcXacts>( 0 );
+
+ public Country()
+ {
+ }
+
+ public Country(String coName, Double coExchange, String coCurrency,
+ Set<IAddress> addresses, Set<ICcXacts> ccXactses)
+ {
+ this.coName = coName;
+ this.coExchange = coExchange;
+ this.coCurrency = coCurrency;
+ this.addresses = addresses;
+ this.ccXactses = ccXactses;
+ }
+
+ @Id
+ @GeneratedValue( strategy = IDENTITY )
+ @Column( name = "CO_ID", unique = true, nullable = false )
+ @Override
+ public Integer getCoId()
+ {
+ return this.coId;
+ }
+
+ @Override
+ public void setCoId(Integer coId)
+ {
+ this.coId = coId;
+ }
+
+ @Column( name = "CO_NAME", length = 50 )
+ @Override
+ public String getCoName()
+ {
+ return this.coName;
+ }
+
+ @Override
+ public void setCoName(String coName)
+ {
+ this.coName = coName;
+ }
+
+ @Column( name = "CO_EXCHANGE", precision = 22, scale = 0 )
+ @Override
+ public Double getCoExchange()
+ {
+ return this.coExchange;
+ }
+
+ @Override
+ public void setCoExchange(Double coExchange)
+ {
+ this.coExchange = coExchange;
+ }
+
+ @Column( name = "CO_CURRENCY", length = 18 )
+ @Override
+ public String getCoCurrency()
+ {
+ return this.coCurrency;
+ }
+
+ @Override
+ public void setCoCurrency(String coCurrency)
+ {
+ this.coCurrency = coCurrency;
+ }
+
+ @OneToMany( targetEntity=Address.class, fetch = FetchType.LAZY, mappedBy = "country" )
+ public Set<IAddress> getAddresses()
+ {
+ return this.addresses;
+ }
+
+ public void setAddresses(Set<IAddress> addresses)
+ {
+ this.addresses = addresses;
+ }
+
+ @OneToMany( targetEntity=CcXacts.class, fetch = FetchType.LAZY, mappedBy = "country" )
+ public Set<ICcXacts> getCcXactses()
+ {
+ return this.ccXactses;
+ }
+
+ public void setCcXactses(Set<ICcXacts> ccXactses)
+ {
+ this.ccXactses = ccXactses;
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Customer.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Customer.java
new file mode 100644
index 0000000..f1b99d3
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Customer.java
@@ -0,0 +1,281 @@
+package eu.cloudscale.showcase.db.model.hibernate;
+
+// Generated May 16, 2013 3:07:18 PM by Hibernate Tools 4.0.0
+
+import static javax.persistence.GenerationType.IDENTITY;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.model.IOrders;
+
+/**
+ * Customer generated by hbm2java
+ */
+@Entity
+@Table( name = "customer", catalog = "tpcw" )
+public class Customer implements ICustomer
+{
+
+ private Integer cId;
+
+ private IAddress address;
+
+ private String CUname;
+
+ private String CPasswd;
+
+ private String CFname;
+
+ private String CLname;
+
+ private String CPhone;
+
+ private String CEmail;
+
+ private Date CSince;
+
+ private Date CLastVisit;
+
+ private Date CLogin;
+
+ private Date CExpiration;
+
+ private Double CDiscount;
+
+ private Double CBalance;
+
+ private Double CYtdPmt;
+
+ private Date CBirthdate;
+
+ private String CData;
+
+ private Set<IOrders> orderses = new HashSet<IOrders>( 0 );
+
+ public Customer()
+ {
+ }
+
+ @Id
+ @GeneratedValue( strategy = IDENTITY )
+ @Column( name = "C_ID", unique = true, nullable = false )
+ public Integer getCId()
+ {
+ return this.cId;
+ }
+
+ public void setCId(Integer CId)
+ {
+ this.cId = CId;
+ }
+
+ @ManyToOne( targetEntity=Address.class, fetch = FetchType.EAGER )
+ @JoinColumn( name = "C_ADDR_ID", nullable = false )
+ public IAddress getAddress()
+ {
+ return this.address;
+ }
+
+ public void setAddress(IAddress address)
+ {
+ this.address = address;
+ }
+
+ @Column( name = "C_UNAME", length = 20 )
+ public String getCUname()
+ {
+ return this.CUname;
+ }
+
+ public void setCUname(String CUname)
+ {
+ this.CUname = CUname;
+ }
+
+ @Column( name = "C_PASSWD", length = 20 )
+ public String getCPasswd()
+ {
+ return this.CPasswd;
+ }
+
+ public void setCPasswd(String CPasswd)
+ {
+ this.CPasswd = CPasswd;
+ }
+
+ @Column( name = "C_FNAME", length = 15 )
+ public String getCFname()
+ {
+ return this.CFname;
+ }
+
+ public void setCFname(String CFname)
+ {
+ this.CFname = CFname;
+ }
+
+ @Column( name = "C_LNAME", length = 15 )
+ public String getCLname()
+ {
+ return this.CLname;
+ }
+
+ public void setCLname(String CLname)
+ {
+ this.CLname = CLname;
+ }
+
+ @Column( name = "C_PHONE", length = 16 )
+ public String getCPhone()
+ {
+ return this.CPhone;
+ }
+
+ public void setCPhone(String CPhone)
+ {
+ this.CPhone = CPhone;
+ }
+
+ @Column( name = "C_EMAIL", length = 50 )
+ public String getCEmail()
+ {
+ return this.CEmail;
+ }
+
+ public void setCEmail(String CEmail)
+ {
+ this.CEmail = CEmail;
+ }
+
+ @Temporal( TemporalType.DATE )
+ @Column( name = "C_SINCE", length = 10 )
+ public Date getCSince()
+ {
+ return this.CSince;
+ }
+
+ public void setCSince(Date CSince)
+ {
+ this.CSince = CSince;
+ }
+
+ @Temporal( TemporalType.DATE )
+ @Column( name = "C_LAST_VISIT", length = 10 )
+ public Date getCLastVisit()
+ {
+ return this.CLastVisit;
+ }
+
+ public void setCLastVisit(Date CLastVisit)
+ {
+ this.CLastVisit = CLastVisit;
+ }
+
+ @Temporal( TemporalType.TIMESTAMP )
+ @Column( name = "C_LOGIN", length = 19 )
+ public Date getCLogin()
+ {
+ return this.CLogin;
+ }
+
+ public void setCLogin(Date CLogin)
+ {
+ this.CLogin = CLogin;
+ }
+
+ @Temporal( TemporalType.TIMESTAMP )
+ @Column( name = "C_EXPIRATION", length = 19 )
+ public Date getCExpiration()
+ {
+ return this.CExpiration;
+ }
+
+ public void setCExpiration(Date CExpiration)
+ {
+ this.CExpiration = CExpiration;
+ }
+
+ @Column( name = "C_DISCOUNT" )
+ public Double getCDiscount()
+ {
+ return this.CDiscount;
+ }
+
+ public void setCDiscount(double c_DISCOUNT)
+ {
+ this.CDiscount = c_DISCOUNT;
+ }
+
+ @Column( name = "C_BALANCE" )
+ public Double getCBalance()
+ {
+ return this.CBalance;
+ }
+
+ public void setCBalance(Double c_BALANCE)
+ {
+ this.CBalance = c_BALANCE;
+ }
+
+ @Column( name = "C_YTD_PMT" )
+ public Double getCYtdPmt()
+ {
+ return this.CYtdPmt;
+ }
+
+ public void setCYtdPmt(Double c_YTD_PMT)
+ {
+ this.CYtdPmt = c_YTD_PMT;
+ }
+
+ @Temporal( TemporalType.DATE )
+ @Column( name = "C_BIRTHDATE", length = 10 )
+ public Date getCBirthdate()
+ {
+ return this.CBirthdate;
+ }
+
+ public void setCBirthdate(Date CBirthdate)
+ {
+ this.CBirthdate = CBirthdate;
+ }
+
+ @Column( name = "C_DATA", length = 65535 )
+ public String getCData()
+ {
+ return this.CData;
+ }
+
+ public void setCData(String CData)
+ {
+ this.CData = CData;
+ }
+
+ @OneToMany( targetEntity=Orders.class, fetch = FetchType.LAZY, mappedBy = "customer" )
+ public Set<IOrders> getOrderses()
+ {
+ return this.orderses;
+ }
+
+ public void setOrderses(Set<IOrders> orderses)
+ {
+ this.orderses = orderses;
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Item.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Item.java
new file mode 100644
index 0000000..ceed572
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Item.java
@@ -0,0 +1,378 @@
+package eu.cloudscale.showcase.db.model.hibernate;
+
+// Generated May 16, 2013 3:07:18 PM by Hibernate Tools 4.0.0
+
+import static javax.persistence.GenerationType.IDENTITY;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+import org.hibernate.annotations.Index;
+
+import eu.cloudscale.showcase.db.model.IAuthor;
+import eu.cloudscale.showcase.db.model.IItem;
+import eu.cloudscale.showcase.db.model.IOrderLine;
+import eu.cloudscale.showcase.db.model.IShoppingCartLine;
+
+/**
+ * Item generated by hbm2java
+ */
+@Entity
+@Table( name = "item", catalog = "tpcw" )
+public class Item implements java.io.Serializable, IItem
+{
+
+ private static final long serialVersionUID = 8806932749710043085L;
+
+ private Integer IId;
+
+ private IAuthor author;
+
+ private String ITitle;
+
+ private Date IPubDate;
+
+ private String IPublisher;
+
+ private String ISubject;
+
+ private String IDesc;
+
+ private Integer IRelated1;
+
+ private Integer IRelated2;
+
+ private Integer IRelated3;
+
+ private Integer IRelated4;
+
+ private Integer IRelated5;
+
+ private String IThumbnail;
+
+ private String IImage;
+
+ private Double ISrp;
+
+ private Double ICost;
+
+ private Date IAvail;
+
+ private Integer IStock;
+
+ private String IIsbn;
+
+ private String IPage;
+
+ private String IBacking;
+
+ private String IDimension;
+
+ private double IRandom;
+
+ private Set<IOrderLine> orderLines = new HashSet<IOrderLine>( 0 );
+
+ private Set<IShoppingCartLine> shoppingCartLines = new HashSet<IShoppingCartLine>( 0 );
+
+ public Item()
+ {
+ }
+
+ @Id
+ @GeneratedValue( strategy = IDENTITY )
+ @Column( name = "I_ID", unique = true, nullable = false )
+ public Integer getIId()
+ {
+ return this.IId;
+ }
+
+ public void setIId(Integer IId)
+ {
+ this.IId = IId;
+ }
+
+ @ManyToOne( targetEntity=Author.class, fetch = FetchType.LAZY )
+ @JoinColumn( name = "I_A_ID", nullable = false )
+ public IAuthor getAuthor()
+ {
+ return this.author;
+ }
+
+ public void setAuthor(IAuthor author)
+ {
+ this.author = author;
+ }
+
+ @Column( name = "I_TITLE", length = 60 )
+ public String getITitle()
+ {
+ return this.ITitle;
+ }
+
+ public void setITitle(String ITitle)
+ {
+ this.ITitle = ITitle;
+ }
+
+ @Temporal( TemporalType.TIMESTAMP )
+ @Column( name = "I_PUB_DATE", length = 19 )
+ public Date getIPubDate()
+ {
+ return this.IPubDate;
+ }
+
+ public void setIPubDate(Date IPubDate)
+ {
+ this.IPubDate = IPubDate;
+ }
+
+ @Column( name = "I_PUBLISHER", length = 60 )
+ public String getIPublisher()
+ {
+ return this.IPublisher;
+ }
+
+ public void setIPublisher(String IPublisher)
+ {
+ this.IPublisher = IPublisher;
+ }
+
+ @Column( name = "I_SUBJECT", length = 60 )
+ public String getISubject()
+ {
+ return this.ISubject;
+ }
+
+ public void setISubject(String ISubject)
+ {
+ this.ISubject = ISubject;
+ }
+
+ @Column( name = "I_DESC", length = 65535 )
+ public String getIDesc()
+ {
+ return this.IDesc;
+ }
+
+ public void setIDesc(String IDesc)
+ {
+ this.IDesc = IDesc;
+ }
+
+ @Column( name = "I_RELATED1" )
+ public Integer getIRelated1()
+ {
+ return this.IRelated1;
+ }
+
+ public void setIRelated1(Integer IRelated1)
+ {
+ this.IRelated1 = IRelated1;
+ }
+
+ @Column( name = "I_RELATED2" )
+ public Integer getIRelated2()
+ {
+ return this.IRelated2;
+ }
+
+ public void setIRelated2(Integer IRelated2)
+ {
+ this.IRelated2 = IRelated2;
+ }
+
+ @Column( name = "I_RELATED3" )
+ public Integer getIRelated3()
+ {
+ return this.IRelated3;
+ }
+
+ public void setIRelated3(Integer IRelated3)
+ {
+ this.IRelated3 = IRelated3;
+ }
+
+ @Column( name = "I_RELATED4" )
+ public Integer getIRelated4()
+ {
+ return this.IRelated4;
+ }
+
+ public void setIRelated4(Integer IRelated4)
+ {
+ this.IRelated4 = IRelated4;
+ }
+
+ @Column( name = "I_RELATED5" )
+ public Integer getIRelated5()
+ {
+ return this.IRelated5;
+ }
+
+ public void setIRelated5(Integer IRelated5)
+ {
+ this.IRelated5 = IRelated5;
+ }
+
+ @Column( name = "I_THUMBNAIL", length = 60 )
+ public String getIThumbnail()
+ {
+ return this.IThumbnail;
+ }
+
+ public void setIThumbnail(String IThumbnail)
+ {
+ this.IThumbnail = IThumbnail;
+ }
+
+ @Column( name = "I_IMAGE", length = 60 )
+ public String getIImage()
+ {
+ return this.IImage;
+ }
+
+ public void setIImage(String IImage)
+ {
+ this.IImage = IImage;
+ }
+
+ @Column( name = "I_SRP" )
+ public Double getISrp()
+ {
+ return this.ISrp;
+ }
+
+ public void setISrp(Double i_SRP)
+ {
+ this.ISrp = i_SRP;
+ }
+
+ @Column( name = "I_COST" )
+ public Double getICost()
+ {
+ return this.ICost;
+ }
+
+ public void setICost(Double i_COST)
+ {
+ this.ICost = i_COST;
+ }
+
+ @Temporal( TemporalType.TIMESTAMP )
+ @Column( name = "I_AVAIL", length = 19 )
+ public Date getIAvail()
+ {
+ return this.IAvail;
+ }
+
+ public void setIAvail(Date IAvail)
+ {
+ this.IAvail = IAvail;
+ }
+
+ @Column( name = "I_STOCK" )
+ public Integer getIStock()
+ {
+ return this.IStock;
+ }
+
+ public void setIStock(Integer IStock)
+ {
+ this.IStock = IStock;
+ }
+
+ @Column( name = "I_ISBN", length = 13 )
+ public String getIIsbn()
+ {
+ return this.IIsbn;
+ }
+
+ public void setIIsbn(String IIsbn)
+ {
+ this.IIsbn = IIsbn;
+ }
+
+ @Column( name = "I_PAGE", length = 4 )
+ public String getIPage()
+ {
+ return this.IPage;
+ }
+
+ public void setIPage(String IPage)
+ {
+ this.IPage = IPage;
+ }
+
+ @Column( name = "I_BACKING", length = 15 )
+ public String getIBacking()
+ {
+ return this.IBacking;
+ }
+
+ public void setIBacking(String IBacking)
+ {
+ this.IBacking = IBacking;
+ }
+
+ @Column( name = "I_DIMENSION", length = 25 )
+ public String getIDimension()
+ {
+ return this.IDimension;
+ }
+
+ public void setIDimension(String IDimension)
+ {
+ this.IDimension = IDimension;
+ }
+
+ @OneToMany( targetEntity=OrderLine.class, fetch = FetchType.LAZY, mappedBy = "item" )
+ public Set<IOrderLine> getOrderLines()
+ {
+ return this.orderLines;
+ }
+
+ public void setOrderLines(Set<IOrderLine> orderLines)
+ {
+ this.orderLines = orderLines;
+ }
+
+ @OneToMany( targetEntity=ShoppingCartLine.class, fetch = FetchType.LAZY, mappedBy = "item" )
+ public Set<IShoppingCartLine> getShoppingCartLines()
+ {
+ return this.shoppingCartLines;
+ }
+
+ public void setShoppingCartLines(Set<IShoppingCartLine> shoppingCartLines)
+ {
+ this.shoppingCartLines = shoppingCartLines;
+ }
+
+ @Override
+ @Column( name="I_RANDOM")
+ public double getIRandom()
+ {
+ return IRandom;
+ }
+
+ @Override
+ public void setIRandom(double num)
+ {
+ IRandom = num;
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/OrderLine.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/OrderLine.java
new file mode 100644
index 0000000..604ca14
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/OrderLine.java
@@ -0,0 +1,116 @@
+package eu.cloudscale.showcase.db.model.hibernate;
+
+// Generated May 16, 2013 3:07:18 PM by Hibernate Tools 4.0.0
+
+import static javax.persistence.GenerationType.IDENTITY;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+
+import eu.cloudscale.showcase.db.model.IItem;
+import eu.cloudscale.showcase.db.model.IOrderLine;
+import eu.cloudscale.showcase.db.model.IOrders;
+
+/**
+ * OrderLine generated by hbm2java
+ */
+@Entity
+@Table( name = "order_line", catalog = "tpcw" )
+public class OrderLine implements IOrderLine
+{
+ private Integer id;
+
+ private IOrders orders;
+
+ private IItem item;
+
+ private Integer olQty;
+
+ private Double olDiscount;
+
+ private String olComment;
+
+ public OrderLine()
+ {
+ }
+
+ @Id
+ @GeneratedValue( strategy = IDENTITY )
+ @Column( name = "OL_ID", unique = true, nullable = false )
+ public Integer getOlId()
+ {
+ return this.id;
+ }
+
+ public void setOlId(Integer olId)
+ {
+ this.id = olId;
+ }
+
+ @ManyToOne( targetEntity=Orders.class, fetch = FetchType.EAGER )
+ @JoinColumn( name = "OL_O_ID", nullable = false )
+ public IOrders getOrders()
+ {
+ return this.orders;
+ }
+
+ public void setOrders(IOrders orders)
+ {
+ this.orders = orders;
+ }
+
+ @ManyToOne( targetEntity=Item.class, fetch = FetchType.EAGER )
+ @JoinColumn( name = "OL_I_ID", nullable = false )
+ public IItem getItem()
+ {
+ return this.item;
+ }
+
+ public void setItem(IItem item)
+ {
+ this.item = item;
+ }
+
+ @Column( name = "OL_QTY" )
+ public Integer getOlQty()
+ {
+ return this.olQty;
+ }
+
+ public void setOlQty(Integer olQty)
+ {
+ this.olQty = olQty;
+ }
+
+ @Column( name = "OL_DISCOUNT" )
+ public Double getOlDiscount()
+ {
+ return this.olDiscount;
+ }
+
+ public void setOlDiscount(Double oL_DISCOUNT)
+ {
+ this.olDiscount = oL_DISCOUNT;
+ }
+
+ @Column( name = "OL_COMMENT", length = 100 )
+ public String getOlComment()
+ {
+ return this.olComment;
+ }
+
+ public void setOlComment(String olComment)
+ {
+ this.olComment = olComment;
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Orders.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Orders.java
new file mode 100644
index 0000000..397dfcb
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/Orders.java
@@ -0,0 +1,218 @@
+package eu.cloudscale.showcase.db.model.hibernate;
+
+// Generated May 16, 2013 3:07:18 PM by Hibernate Tools 4.0.0
+
+import static javax.persistence.GenerationType.IDENTITY;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.ICcXacts;
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.model.IOrderLine;
+import eu.cloudscale.showcase.db.model.IOrders;
+
+@Entity
+@Table( name = "orders", catalog = "tpcw" )
+public class Orders implements IOrders
+{
+
+ private Integer id;
+
+ private IAddress addressByOShipAddrId;
+
+ private ICustomer customer;
+
+ private IAddress addressByOBillAddrId;
+
+ private Date ODate;
+
+ private Double OSubTotal;
+
+ private Double OTax;
+
+ private Double OTotal;
+
+ private String OShipType;
+
+ private Date OShipDate;
+
+ private String OStatus;
+
+ private Set<ICcXacts> ccXactses = new HashSet<ICcXacts>( 0 );
+
+ private Set<IOrderLine> orderLines = new HashSet<IOrderLine>( 0 );
+
+ public Orders()
+ {
+
+ }
+
+ @Id
+ @GeneratedValue( strategy = IDENTITY )
+ @Column( name = "O_ID", unique = true, nullable = false )
+ public Integer getOId()
+
+ {
+ return this.id;
+ }
+
+ public void setOId(Integer OId)
+ {
+ this.id = OId;
+ }
+
+ @ManyToOne( targetEntity=Address.class, fetch = FetchType.EAGER )
+ @JoinColumn( name = "O_SHIP_ADDR_ID", nullable = false )
+ public IAddress getAddressByOShipAddrId()
+ {
+ return this.addressByOShipAddrId;
+ }
+
+ public void setAddressByOShipAddrId(IAddress addressByOShipAddrId)
+ {
+ this.addressByOShipAddrId = addressByOShipAddrId;
+ }
+
+ @ManyToOne( targetEntity=Customer.class, fetch = FetchType.EAGER )
+ @JoinColumn( name = "O_C_ID", nullable = false )
+ public ICustomer getCustomer()
+ {
+ return this.customer;
+ }
+
+ public void setCustomer(ICustomer customer)
+ {
+ this.customer = customer;
+ }
+
+ @ManyToOne( targetEntity=Address.class, fetch = FetchType.EAGER )
+ @JoinColumn( name = "O_BILL_ADDR_ID", nullable = false )
+ public IAddress getAddressByOBillAddrId()
+ {
+ return this.addressByOBillAddrId;
+ }
+
+ public void setAddressByOBillAddrId(IAddress addressByOBillAddrId)
+ {
+ this.addressByOBillAddrId = addressByOBillAddrId;
+ }
+
+ @Temporal( TemporalType.DATE )
+ @Column( name = "O_DATE", length = 19 )
+ public Date getODate()
+ {
+ return this.ODate;
+ }
+
+ public void setODate(Date ODate)
+ {
+ this.ODate = ODate;
+ }
+
+ @Column( name = "O_SUB_TOTAL" )
+ public Double getOSubTotal()
+ {
+ return this.OSubTotal;
+ }
+
+ public void setOSubTotal(Double o_SUB_TOTAL)
+ {
+ this.OSubTotal = o_SUB_TOTAL;
+ }
+
+ @Column( name = "O_TAX" )
+ public Double getOTax()
+ {
+ return this.OTax;
+ }
+
+ public void setOTax(Double o_TAX)
+ {
+ this.OTax = o_TAX;
+ }
+
+ @Column( name = "O_TOTAL" )
+ public Double getOTotal()
+ {
+ return this.OTotal;
+ }
+
+ public void setOTotal(double o_TOTAL)
+ {
+ this.OTotal = o_TOTAL;
+ }
+
+ @Column( name = "O_SHIP_TYPE", length = 10 )
+ public String getOShipType()
+ {
+ return this.OShipType;
+ }
+
+ public void setOShipType(String OShipType)
+ {
+ this.OShipType = OShipType;
+ }
+
+ @Temporal( TemporalType.DATE )
+ @Column( name = "O_SHIP_DATE", length = 19 )
+ public Date getOShipDate()
+ {
+ return this.OShipDate;
+ }
+
+ public void setOShipDate(Date OShipDate)
+ {
+ this.OShipDate = OShipDate;
+ }
+
+ @Column( name = "O_STATUS", length = 15 )
+ public String getOStatus()
+ {
+ return this.OStatus;
+ }
+
+ public void setOStatus(String OStatus)
+ {
+ this.OStatus = OStatus;
+ }
+
+ @OneToMany( targetEntity=CcXacts.class, fetch = FetchType.LAZY, mappedBy = "orders" )
+ public Set<ICcXacts> getCcXactses()
+ {
+ return this.ccXactses;
+ }
+
+ public void setCcXactses(Set<ICcXacts> ccXactses)
+ {
+ this.ccXactses = ccXactses;
+ }
+
+ @OneToMany( targetEntity=OrderLine.class, fetch = FetchType.LAZY, mappedBy = "orders" )
+ public Set<IOrderLine> getOrderLines()
+ {
+ return this.orderLines;
+ }
+
+ public void setOrderLines(Set<IOrderLine> orderLines)
+ {
+ this.orderLines = orderLines;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/ShoppingCart.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/ShoppingCart.java
new file mode 100644
index 0000000..d5cc825
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/ShoppingCart.java
@@ -0,0 +1,87 @@
+package eu.cloudscale.showcase.db.model.hibernate;
+
+// Generated May 16, 2013 3:07:18 PM by Hibernate Tools 4.0.0
+
+import static javax.persistence.GenerationType.IDENTITY;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import eu.cloudscale.showcase.db.model.IShoppingCart;
+import eu.cloudscale.showcase.db.model.IShoppingCartLine;
+
+
+/**
+ * ShoppingCart generated by hbm2java
+ */
+@Entity
+@Table( name = "shopping_cart", catalog = "tpcw" )
+public class ShoppingCart implements IShoppingCart
+{
+ private Integer scId;
+
+ private Date scTime;
+
+ private Set<IShoppingCartLine> shoppingCartLines = new HashSet<IShoppingCartLine>( 0 );
+
+ public ShoppingCart()
+ {
+ }
+
+ public ShoppingCart(Date scTime)
+ {
+ this.scTime = scTime;
+ }
+
+ @OneToMany( targetEntity=ShoppingCartLine.class, fetch = FetchType.LAZY, mappedBy = "shoppingCart" )
+ public Set<IShoppingCartLine> getShoppingCartLines()
+ {
+ return shoppingCartLines;
+ }
+
+ public void setShoppingCartLines(Set<IShoppingCartLine> shoppingCartLines)
+ {
+ this.shoppingCartLines = shoppingCartLines;
+ }
+
+ @Id
+ @GeneratedValue( strategy = IDENTITY )
+ @Column( name = "SC_ID", unique = true, nullable = false )
+ @Override
+ public Integer getScId()
+ {
+ return this.scId;
+ }
+
+ @Override
+ public void setScId(Integer scId)
+ {
+ this.scId = scId;
+ }
+
+ @Temporal( TemporalType.TIMESTAMP )
+ @Column( name = "SC_TIME", length = 19 )
+ @Override
+ public Date getScTime()
+ {
+ return this.scTime;
+ }
+
+ @Override
+ public void setScTime(Date scTime)
+ {
+ this.scTime = scTime;
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/ShoppingCartLine.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/ShoppingCartLine.java
new file mode 100644
index 0000000..c3ad7e4
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/hibernate/ShoppingCartLine.java
@@ -0,0 +1,95 @@
+package eu.cloudscale.showcase.db.model.hibernate;
+
+// Generated May 16, 2013 3:07:18 PM by Hibernate Tools 4.0.0
+
+import static javax.persistence.GenerationType.IDENTITY;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+import eu.cloudscale.showcase.db.model.IItem;
+import eu.cloudscale.showcase.db.model.IShoppingCart;
+import eu.cloudscale.showcase.db.model.IShoppingCartLine;
+
+/**
+ * ShoppingCartLine generated by hbm2java
+ */
+@Entity
+@Table( name = "shopping_cart_line", catalog = "tpcw" )
+public class ShoppingCartLine implements IShoppingCartLine
+{
+ private Integer sclId;
+
+ private IItem item;
+
+ private Integer sclQty;
+
+ private IShoppingCart shoppingCart;
+
+ public ShoppingCartLine()
+ {
+ }
+
+ @ManyToOne( targetEntity=ShoppingCart.class, fetch = FetchType.LAZY )
+ @JoinColumn( name = "SCL_SC_ID", nullable = false )
+ @Override
+ public IShoppingCart getShoppingCart()
+ {
+ return shoppingCart;
+ }
+
+ @Override
+ public void setShoppingCart(IShoppingCart shoppingCart)
+ {
+ this.shoppingCart = shoppingCart;
+ }
+
+
+ @Id
+ @GeneratedValue( strategy = IDENTITY )
+ @Column( name = "SCL_ID", unique = true, nullable = false )
+ @Override
+ public Integer getSclId()
+ {
+ return this.sclId;
+ }
+
+ @Override
+ public void setSclId( Integer sclScId )
+ {
+ this.sclId = sclScId;
+ }
+
+ @ManyToOne( targetEntity=Item.class, fetch = FetchType.EAGER )
+ @JoinColumn( name = "SCL_I_ID", nullable = false )
+ @Override
+ public IItem getItem()
+ {
+ return this.item;
+ }
+
+ @Override
+ public void setItem(IItem item)
+ {
+ this.item = item;
+ }
+
+ @Column( name = "SCL_QTY" )
+ @Override
+ public Integer getSclQty()
+ {
+ return this.sclQty;
+ }
+
+ @Override
+ public void setSclQty(Integer sclQty)
+ {
+ this.sclQty = sclQty;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IAddress.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IAddress.java
new file mode 100644
index 0000000..21df49c
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IAddress.java
@@ -0,0 +1,40 @@
+package eu.cloudscale.showcase.db.model;
+
+import java.util.Set;
+
+
+
+public interface IAddress
+{
+
+ public Integer getAddrId();
+
+ public void setAddrId(Integer addrId);
+
+ public ICountry getCountry();
+
+ public void setCountry(ICountry country);
+
+ public String getAddrStreet1();
+
+ public void setAddrStreet1(String addrStreet1);
+
+ public String getAddrStreet2();
+
+ public void setAddrStreet2(String addrStreet2);
+
+ public String getAddrCity();
+
+ public void setAddrCity(String addrCity);
+
+ public String getAddrState();
+
+ public void setAddrState(String addrState);
+
+ public String getAddrZip();
+
+ public void setAddrZip(String addrZip);
+
+ public Set<ICustomer> getCustomers();
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IAuthor.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IAuthor.java
new file mode 100644
index 0000000..a1ebe5a
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IAuthor.java
@@ -0,0 +1,34 @@
+package eu.cloudscale.showcase.db.model;
+
+import java.util.Date;
+
+
+
+public interface IAuthor
+{
+
+ public Integer getAId();
+
+ public void setAId(Integer AId);
+
+ public String getAFname();
+
+ public void setAFname(String AFname);
+
+ public String getALname();
+
+ public void setALname(String ALname);
+
+ public String getAMname();
+
+ public void setAMname(String AMname);
+
+ public Date getADob();
+
+ public void setADob(Date ADob);
+
+ public String getABio();
+
+ public void setABio(String ABio);
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/ICcXacts.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/ICcXacts.java
new file mode 100644
index 0000000..d7e3add
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/ICcXacts.java
@@ -0,0 +1,50 @@
+package eu.cloudscale.showcase.db.model;
+
+import java.util.Date;
+
+
+
+public interface ICcXacts
+{
+
+ public Integer getId();
+
+ public void setId(Integer id);
+
+ public ICountry getCountry();
+
+ public void setCountry(ICountry country);
+
+ public IOrders getOrders();
+
+ public String getCxType();
+
+ public void setCxType(String cxType);
+
+ public Integer getCxNum();
+
+ public void setCxNum(Integer cxNum);
+
+ public String getCxName();
+
+ public void setCxName(String cxName);
+
+ public Date getCxExpiry();
+
+ public void setCxExpiry(Date cxExpiry);
+
+ public IAuthor getCxAuthId();
+
+ public void setCxAuthId(IAuthor cxAuthId);
+
+ public Double getCxXactAmt();
+
+ public void setCxXactAmt(Double o_TOTAL);
+
+ public Date getCxXactDate();
+
+ public void setCxXactDate(Date cxXactDate);
+
+ public void setOrders(IOrders orders);
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/ICountry.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/ICountry.java
new file mode 100644
index 0000000..376b67c
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/ICountry.java
@@ -0,0 +1,23 @@
+package eu.cloudscale.showcase.db.model;
+
+
+public interface ICountry
+{
+
+ public Integer getCoId();
+
+ public void setCoId(Integer coId);
+
+ public String getCoName();
+
+ public void setCoName(String coName);
+
+ public Double getCoExchange();
+
+ public void setCoExchange(Double coExchange);
+
+ public String getCoCurrency();
+
+ public void setCoCurrency(String coCurrency);
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/ICustomer.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/ICustomer.java
new file mode 100644
index 0000000..4046c24
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/ICustomer.java
@@ -0,0 +1,76 @@
+package eu.cloudscale.showcase.db.model;
+
+import java.util.Date;
+
+
+public interface ICustomer
+{
+
+ public Integer getCId();
+
+ public void setCId(Integer CId);
+
+ public IAddress getAddress();
+
+ public void setAddress(IAddress address);
+
+ public String getCUname();
+
+ public void setCUname(String CUname);
+
+ public String getCPasswd();
+
+ public void setCPasswd(String CPasswd);
+
+ public String getCFname();
+
+ public void setCFname(String CFname);
+
+ public String getCLname();
+
+ public void setCLname(String CLname);
+
+ public String getCPhone();
+
+ public void setCData(String CData);
+
+ public String getCData();
+
+ public void setCBirthdate(Date CBirthdate);
+
+ public Date getCBirthdate();
+
+ public void setCYtdPmt(Double c_YTD_PMT);
+
+ public Double getCYtdPmt();
+
+ public void setCBalance(Double c_BALANCE);
+
+ public Double getCBalance();
+
+ public void setCDiscount(double c_DISCOUNT);
+
+ public Double getCDiscount();
+
+ public void setCExpiration(Date CExpiration);
+
+ public Date getCExpiration();
+
+ public void setCLogin(Date CLogin);
+
+ public Date getCLogin();
+
+ public void setCLastVisit(Date CLastVisit);
+
+ public Date getCLastVisit();
+
+ public void setCSince(Date CSince);
+
+ public Date getCSince();
+
+ public void setCEmail(String CEmail);
+
+ public String getCEmail();
+
+ public void setCPhone(String CPhone);
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IItem.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IItem.java
new file mode 100644
index 0000000..700e485
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IItem.java
@@ -0,0 +1,100 @@
+package eu.cloudscale.showcase.db.model;
+
+import java.util.Date;
+
+
+public interface IItem
+{
+
+ public Integer getIId();
+
+ public void setIDimension(String IDimension);
+
+ public String getIDimension();
+
+ public void setIBacking(String IBacking);
+
+ public String getIBacking();
+
+ public void setIPage(String IPage);
+
+ public String getIPage();
+
+ public void setIIsbn(String IIsbn);
+
+ public String getIIsbn();
+
+ public void setIStock(Integer IStock);
+
+ public Integer getIStock();
+
+ public void setIAvail(Date IAvail);
+
+ public Date getIAvail();
+
+ public void setICost(Double i_COST);
+
+ public Double getICost();
+
+ public void setISrp(Double i_SRP);
+
+ public Double getISrp();
+
+ public void setIImage(String IImage);
+
+ public String getIImage();
+
+ public void setIThumbnail(String IThumbnail);
+
+ public String getIThumbnail();
+
+ public void setIRelated5(Integer IRelated5);
+
+ public Integer getIRelated5();
+
+ public void setIRelated4(Integer IRelated4);
+
+ public Integer getIRelated4();
+
+ public void setIRelated3(Integer IRelated3);
+
+ public Integer getIRelated3();
+
+ public void setIRelated2(Integer IRelated2);
+
+ public Integer getIRelated2();
+
+ public void setIRelated1(Integer IRelated1);
+
+ public Integer getIRelated1();
+
+ public void setIDesc(String IDesc);
+
+ public String getIDesc();
+
+ public void setISubject(String ISubject);
+
+ public String getISubject();
+
+ public void setIPublisher(String IPublisher);
+
+ public String getIPublisher();
+
+ public void setIPubDate(Date IPubDate);
+
+ public Date getIPubDate();
+
+ public void setITitle(String ITitle);
+
+ public String getITitle();
+
+ public void setAuthor(IAuthor author);
+
+ public IAuthor getAuthor();
+
+ public void setIId(Integer IId);
+
+ public double getIRandom();
+
+ public void setIRandom(double num);
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IOrderLine.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IOrderLine.java
new file mode 100644
index 0000000..581c9c8
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IOrderLine.java
@@ -0,0 +1,31 @@
+package eu.cloudscale.showcase.db.model;
+
+
+public interface IOrderLine
+{
+
+ public Integer getOlId();
+
+ public void setOlId(Integer olId);
+
+ public IOrders getOrders();
+
+ public void setOrders(IOrders orders);
+
+ public IItem getItem();
+
+ public void setItem(IItem item);
+
+ public Integer getOlQty();
+
+ public void setOlQty(Integer olQty);
+
+ public Double getOlDiscount();
+
+ public void setOlDiscount(Double oL_DISCOUNT);
+
+ public String getOlComment();
+
+ public void setOlComment(String olComment);
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IOrders.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IOrders.java
new file mode 100644
index 0000000..6b0ad44
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IOrders.java
@@ -0,0 +1,56 @@
+package eu.cloudscale.showcase.db.model;
+
+import java.util.Date;
+import java.util.Set;
+
+public interface IOrders
+{
+
+ public Integer getOId();
+
+ public void setOId(Integer OId);
+
+ IAddress getAddressByOShipAddrId();
+
+ void setAddressByOShipAddrId(IAddress addressByOShipAddrId);
+
+ ICustomer getCustomer();
+
+ void setCustomer(ICustomer customer);
+
+ IAddress getAddressByOBillAddrId();
+
+ void setAddressByOBillAddrId(IAddress addressByOBillAddrId);
+
+
+ void setOStatus(String OStatus);
+
+ String getOStatus();
+
+ void setOShipDate(Date OShipDate);
+
+ Date getOShipDate();
+
+ void setOShipType(String OShipType);
+
+ String getOShipType();
+
+ void setOTotal(double o_TOTAL);
+
+ Double getOTotal();
+
+ void setOTax(Double o_TAX);
+
+ Double getOTax();
+
+ void setOSubTotal(Double o_SUB_TOTAL);
+
+ Double getOSubTotal();
+
+ void setODate(Date ODate);
+
+ Date getODate();
+
+ public Set<IOrderLine> getOrderLines();
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IShoppingCart.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IShoppingCart.java
new file mode 100644
index 0000000..7b69ab3
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IShoppingCart.java
@@ -0,0 +1,20 @@
+package eu.cloudscale.showcase.db.model;
+
+import java.util.Date;
+import java.util.Set;
+
+
+public interface IShoppingCart
+{
+
+ public void setScTime(Date scTime);
+
+ public Date getScTime();
+
+ public void setScId(Integer scId);
+
+ public Integer getScId();
+
+ public Set<IShoppingCartLine> getShoppingCartLines();
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IShoppingCartLine.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IShoppingCartLine.java
new file mode 100644
index 0000000..3a8b308
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/IShoppingCartLine.java
@@ -0,0 +1,24 @@
+package eu.cloudscale.showcase.db.model;
+
+
+
+public interface IShoppingCartLine
+{
+
+ public IShoppingCart getShoppingCart();
+
+ public void setShoppingCart(IShoppingCart shoppingCart);
+
+ public Integer getSclId();
+
+ public void setSclId(Integer sclScId);
+
+ public IItem getItem();
+
+ public void setItem(IItem item);
+
+ public Integer getSclQty();
+
+ public void setSclQty(Integer sclQty);
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Address.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Address.java
new file mode 100644
index 0000000..9e13fb4
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Address.java
@@ -0,0 +1,157 @@
+package eu.cloudscale.showcase.db.model.mongo;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.bson.types.ObjectId;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+import org.springframework.stereotype.Component;
+
+import eu.cloudscale.showcase.db.common.DatabaseHelper;
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.ICountry;
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.services.MongoService;
+
+@Component
+@Document( collection = "address" )
+public class Address implements IAddress, Serializable
+{
+ @Autowired
+ private MongoService service;
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 926688150220849693L;
+
+ @Id
+ private ObjectId id;
+
+ private Integer addrId;
+
+ private Integer coId;
+
+ private String addrStreet1;
+
+ private String addrStreet2;
+
+ private String addrCity;
+
+ private String addrState;
+
+ private String addrZip;
+
+ public Address()
+ {
+
+ }
+
+ public void setId(ObjectId id)
+ {
+ this.id = id;
+ }
+
+ public ObjectId getId()
+ {
+ return this.id;
+ }
+
+ @Override
+ public Integer getAddrId()
+ {
+ return addrId;
+ }
+
+ @Override
+ public void setAddrId(Integer addrId)
+ {
+ this.addrId = addrId;
+ }
+
+ @Override
+ public ICountry getCountry()
+ {
+ return DatabaseHelper.getDatabase().getCountryDaoImpl().findById( this.coId );
+ }
+
+ @Override
+ public void setCountry(ICountry country)
+ {
+ this.coId = country.getCoId();
+ }
+
+ @Override
+ public String getAddrStreet1()
+ {
+ return this.addrStreet1;
+ }
+
+ @Override
+ public void setAddrStreet1(String addrStreet1)
+ {
+ this.addrStreet1 = addrStreet1;
+ }
+
+ @Override
+ public String getAddrStreet2()
+ {
+ return this.addrStreet2;
+ }
+
+ @Override
+ public void setAddrStreet2(String addrStreet2)
+ {
+ this.addrStreet2 = addrStreet2;
+ }
+
+ @Override
+ public String getAddrCity()
+ {
+ return this.addrCity;
+ }
+
+ @Override
+ public void setAddrCity(String addrCity)
+ {
+ this.addrCity = addrCity;
+ }
+
+ @Override
+ public String getAddrState()
+ {
+ return this.addrState;
+ }
+
+ @Override
+ public void setAddrState(String addrState)
+ {
+ this.addrState = addrState;
+ }
+
+ @Override
+ public String getAddrZip()
+ {
+ return this.addrZip;
+ }
+
+ @Override
+ public void setAddrZip(String addrZip)
+ {
+ this.addrZip = addrZip;
+ }
+
+ @Override
+ public Set<ICustomer> getCustomers()
+ {
+ if( this.addrId == null )
+ return new HashSet<ICustomer>(0);
+
+ IAddress address = DatabaseHelper.getDatabase().getAddressDaoImpl().findById( this.addrId );
+ return new HashSet<ICustomer>(service.getCustomerDaoImpl().findByAddress( address ));
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Author.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Author.java
new file mode 100644
index 0000000..ba30c88
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Author.java
@@ -0,0 +1,135 @@
+package eu.cloudscale.showcase.db.model.mongo;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import org.bson.types.ObjectId;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import eu.cloudscale.showcase.db.model.IAuthor;
+
+@Document( collection = "author" )
+public class Author implements IAuthor, Serializable
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -658143403409650089L;
+
+ @Id
+ private ObjectId id;
+
+ private Integer authorId;
+
+ private String AFname;
+
+ private String ALname;
+
+ private String AMname;
+
+ private Date ADob;
+
+ private String ABio;
+
+ private String lNameSoundex;
+
+ public Author()
+ {
+
+ }
+
+ public void setId(ObjectId id)
+ {
+ this.id = id;
+ }
+
+ public ObjectId getId()
+ {
+ return this.id;
+ }
+
+ @Override
+ public Integer getAId()
+ {
+ return this.authorId;
+ }
+
+ @Override
+ public void setAId(Integer AId)
+ {
+ this.authorId = AId;
+ }
+
+ @Override
+ public String getAFname()
+ {
+ return this.AFname;
+ }
+
+ @Override
+ public void setAFname(String AFname)
+ {
+ this.AFname = AFname;
+ }
+
+ @Override
+ public String getALname()
+ {
+ return this.ALname;
+ }
+
+ @Override
+ public void setALname(String ALname)
+ {
+ this.ALname = ALname;
+ }
+
+ @Override
+ public String getAMname()
+ {
+ return this.AMname;
+ }
+
+ @Override
+ public void setAMname(String AMname)
+ {
+ this.AMname = AMname;
+ }
+
+ @Override
+ public Date getADob()
+ {
+ return this.ADob;
+ }
+
+ @Override
+ public void setADob(Date ADob)
+ {
+ this.ADob = ADob;
+ }
+
+ @Override
+ public String getABio()
+ {
+ return this.ABio;
+ }
+
+ @Override
+ public void setABio(String ABio)
+ {
+ this.ABio = ABio;
+ }
+
+ public String getlNameSoundex()
+ {
+ return lNameSoundex;
+ }
+
+ public void setlNameSoundex(String lNameSoundex)
+ {
+ this.lNameSoundex = lNameSoundex;
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/CcXacts.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/CcXacts.java
new file mode 100644
index 0000000..419a988
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/CcXacts.java
@@ -0,0 +1,183 @@
+package eu.cloudscale.showcase.db.model.mongo;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import org.bson.types.ObjectId;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+import org.springframework.stereotype.Component;
+
+import eu.cloudscale.showcase.db.IService;
+import eu.cloudscale.showcase.db.common.DatabaseHelper;
+import eu.cloudscale.showcase.db.model.IAuthor;
+import eu.cloudscale.showcase.db.model.ICcXacts;
+import eu.cloudscale.showcase.db.model.ICountry;
+import eu.cloudscale.showcase.db.model.IOrders;
+import eu.cloudscale.showcase.db.services.MongoService;
+
+@Component
+@Document( collection = "ccxacts" )
+public class CcXacts implements ICcXacts, Serializable
+{
+
+// @Autowired
+// @Qualifier("service")
+// private IService service;;
+
+ private static final long serialVersionUID = -8752879558532267562L;
+
+ @Id
+ private ObjectId id;
+
+ private Integer ccXactsId;
+
+ private Integer cxCoId;
+
+ private Integer cxOId;
+
+ private String cxType;
+
+ private Integer cxNum;
+
+ private String cxName;
+
+ private Date cxExpiry;
+
+ private Integer cxAuthId;
+
+ private Double cxXactAmt;
+
+ private Date cxXactDate;
+
+ public CcXacts()
+ {
+ }
+
+ public void setId(ObjectId id)
+ {
+ this.id = id;
+ }
+
+ @Override
+ public Integer getId()
+ {
+ return this.ccXactsId;
+ }
+
+ @Override
+ public void setId(Integer id)
+ {
+ this.ccXactsId = id;
+ }
+
+ @Override
+ public ICountry getCountry()
+ {
+ return DatabaseHelper.getDatabase().getCountryDaoImpl().findById( this.cxCoId );
+ }
+
+ @Override
+ public void setCountry(ICountry country)
+ {
+ this.cxCoId = country.getCoId();
+ }
+
+ @Override
+ public IOrders getOrders()
+ {
+ return DatabaseHelper.getDatabase().getOrdersDaoImpl().findById( this.cxOId );
+ }
+
+ @Override
+ public String getCxType()
+ {
+ return this.cxType;
+ }
+
+ @Override
+ public void setCxType(String cxType)
+ {
+ this.cxType = cxType;
+ }
+
+ @Override
+ public Integer getCxNum()
+ {
+ return this.cxNum;
+ }
+
+ @Override
+ public void setCxNum(Integer cxNum)
+ {
+ this.cxNum = cxNum;
+ }
+
+ @Override
+ public String getCxName()
+ {
+ return this.cxName;
+ }
+
+ @Override
+ public void setCxName(String cxName)
+ {
+ this.cxName = cxName;
+ }
+
+ @Override
+ public Date getCxExpiry()
+ {
+ return this.cxExpiry;
+ }
+
+ @Override
+ public void setCxExpiry(Date cxExpiry)
+ {
+ this.cxExpiry = cxExpiry;
+ }
+
+ @Override
+ public IAuthor getCxAuthId()
+ {
+ return DatabaseHelper.getDatabase().getAuthorDaoImpl().findById( this.cxAuthId );
+ }
+
+ @Override
+ public void setCxAuthId(IAuthor cxAuthId)
+ {
+ this.cxAuthId = cxAuthId.getAId();
+ }
+
+ @Override
+ public Double getCxXactAmt()
+ {
+ return this.cxXactAmt;
+ }
+
+ @Override
+ public void setCxXactAmt(Double o_TOTAL)
+ {
+ this.cxXactAmt = o_TOTAL;
+ }
+
+ @Override
+ public Date getCxXactDate()
+ {
+ return this.cxXactDate;
+ }
+
+ @Override
+ public void setCxXactDate(Date cxXactDate)
+ {
+ this.cxXactDate = cxXactDate;
+ }
+
+ @Override
+ public void setOrders(IOrders orders)
+ {
+ this.cxOId = orders.getOId();
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Country.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Country.java
new file mode 100644
index 0000000..12179c7
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Country.java
@@ -0,0 +1,93 @@
+package eu.cloudscale.showcase.db.model.mongo;
+
+import java.io.Serializable;
+
+import org.bson.types.ObjectId;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import eu.cloudscale.showcase.db.model.ICountry;
+
+@Document( collection = "country" )
+public class Country implements ICountry, Serializable
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2938841459454938022L;
+
+ @Id
+ private ObjectId id;
+
+ private Integer coId;
+
+ private String coName;
+
+ private Double coExchange;
+
+ private String coCurrency;
+
+ public Country()
+ {
+ }
+
+ public ObjectId getId()
+ {
+ return id;
+ }
+
+ public void setId(ObjectId id)
+ {
+ this.id = id;
+ }
+
+ @Override
+ public Integer getCoId()
+ {
+ return this.coId;
+ }
+
+ @Override
+ public void setCoId(Integer coId)
+ {
+ this.coId = coId;
+ }
+
+ @Override
+ public String getCoName()
+ {
+ return this.coName;
+ }
+
+ @Override
+ public void setCoName(String coName)
+ {
+ this.coName = coName;
+ }
+
+ @Override
+ public Double getCoExchange()
+ {
+ return this.coExchange;
+ }
+
+ @Override
+ public void setCoExchange(Double coExchange)
+ {
+ this.coExchange = coExchange;
+ }
+
+ @Override
+ public String getCoCurrency()
+ {
+ return this.coCurrency;
+ }
+
+ @Override
+ public void setCoCurrency(String coCurrency)
+ {
+ this.coCurrency = coCurrency;
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Customer.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Customer.java
new file mode 100644
index 0000000..e74a230
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Customer.java
@@ -0,0 +1,283 @@
+package eu.cloudscale.showcase.db.model.mongo;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import org.bson.types.ObjectId;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+import org.springframework.stereotype.Component;
+
+import eu.cloudscale.showcase.db.IService;
+import eu.cloudscale.showcase.db.common.DatabaseHelper;
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.services.MongoService;
+
+@Component
+@Document( collection = "customer" )
+public class Customer implements ICustomer, Serializable
+{
+ @Autowired
+ @Qualifier("service")
+ private IService service;
+
+ private static final long serialVersionUID = 1920560375336316671L;
+
+ @Id
+ private ObjectId id;
+
+ private Integer cId;
+
+ private Integer addrId;
+
+ private String cUname;
+
+ private String cPasswd;
+
+ private String cFname;
+
+ private String cLname;
+
+ private String cPhone;
+
+ private String cEmail;
+
+ private Date cSince;
+
+ private Date cLastVisit;
+
+ private Date cLogin;
+
+ private Date cExpiration;
+
+ private Double cDiscount;
+
+ private Double cBalance;
+
+ private Double cYtdPmt;
+
+ private Date cBirthdate;
+
+ private String cData;
+
+ public Customer()
+ {
+ }
+
+ public ObjectId getId()
+ {
+ return id;
+ }
+
+ public void setId(ObjectId id)
+ {
+ this.id = id;
+ }
+
+ @Override
+ public Integer getCId()
+ {
+ return this.cId;
+ }
+
+ @Override
+ public void setCId(Integer CId)
+ {
+ this.cId = CId;
+ }
+
+ @Override
+ public IAddress getAddress()
+ {
+ return DatabaseHelper.getDatabase().getAddressDaoImpl().findById( addrId );
+ }
+
+ @Override
+ public void setAddress(IAddress address)
+ {
+ this.addrId = address.getAddrId();
+ }
+
+ @Override
+ public String getCUname()
+ {
+ return this.cUname;
+ }
+
+ @Override
+ public void setCUname(String CUname)
+ {
+ this.cUname = CUname;
+ }
+
+ @Override
+ public String getCPasswd()
+ {
+ return this.cPasswd;
+ }
+
+ @Override
+ public void setCPasswd(String CPasswd)
+ {
+ this.cPasswd = CPasswd;
+ }
+
+ @Override
+ public String getCFname()
+ {
+ return this.cFname;
+ }
+
+ @Override
+ public void setCFname(String CFname)
+ {
+ this.cFname = CFname;
+ }
+
+ @Override
+ public String getCLname()
+ {
+ return this.cLname;
+ }
+
+ @Override
+ public void setCLname(String CLname)
+ {
+ this.cLname = CLname;
+ }
+
+ @Override
+ public String getCPhone()
+ {
+ return this.cPhone;
+ }
+
+ @Override
+ public void setCPhone(String CPhone)
+ {
+ this.cPhone = CPhone;
+ }
+
+ @Override
+ public String getCEmail()
+ {
+ return this.cEmail;
+ }
+
+ @Override
+ public void setCEmail(String CEmail)
+ {
+ this.cEmail = CEmail;
+ }
+
+ @Override
+ public Date getCSince()
+ {
+ return this.cSince;
+ }
+
+ @Override
+ public void setCSince(Date CSince)
+ {
+ this.cSince = CSince;
+ }
+
+ @Override
+ public Date getCLastVisit()
+ {
+ return this.cLastVisit;
+ }
+
+ @Override
+ public void setCLastVisit(Date CLastVisit)
+ {
+ this.cLastVisit = CLastVisit;
+ }
+
+ @Override
+ public Date getCLogin()
+ {
+ return this.cLogin;
+ }
+
+ @Override
+ public void setCLogin(Date CLogin)
+ {
+ this.cLogin = CLogin;
+ }
+
+ @Override
+ public Date getCExpiration()
+ {
+ return this.cExpiration;
+ }
+
+ @Override
+ public void setCExpiration(Date CExpiration)
+ {
+ this.cExpiration = CExpiration;
+ }
+
+ @Override
+ public Double getCDiscount()
+ {
+ return this.cDiscount;
+ }
+
+ @Override
+ public void setCDiscount(double c_DISCOUNT)
+ {
+ this.cDiscount = c_DISCOUNT;
+ }
+
+ @Override
+ public Double getCBalance()
+ {
+ return this.cBalance;
+ }
+
+ @Override
+ public void setCBalance(Double c_BALANCE)
+ {
+ this.cBalance = c_BALANCE;
+ }
+
+ @Override
+ public Double getCYtdPmt()
+ {
+ return this.cYtdPmt;
+ }
+
+ @Override
+ public void setCYtdPmt(Double c_YTD_PMT)
+ {
+ this.cYtdPmt = c_YTD_PMT;
+ }
+
+ @Override
+ public Date getCBirthdate()
+ {
+ return this.cBirthdate;
+ }
+
+ @Override
+ public void setCBirthdate(Date CBirthdate)
+ {
+ this.cBirthdate = CBirthdate;
+ }
+
+ @Override
+ public String getCData()
+ {
+ return this.cData;
+ }
+
+ @Override
+ public void setCData(String CData)
+ {
+ this.cData = CData;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Item.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Item.java
new file mode 100644
index 0000000..910c172
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Item.java
@@ -0,0 +1,401 @@
+package eu.cloudscale.showcase.db.model.mongo;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import org.bson.types.ObjectId;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+import org.springframework.stereotype.Component;
+
+import eu.cloudscale.showcase.db.IService;
+import eu.cloudscale.showcase.db.common.DatabaseHelper;
+import eu.cloudscale.showcase.db.model.IAuthor;
+import eu.cloudscale.showcase.db.model.IItem;
+
+@Component
+@Document( collection = "item" )
+public class Item implements IItem, Serializable
+{
+
+ @Autowired
+ @Qualifier("service")
+ private IService service;
+
+ private static final long serialVersionUID = -1311610290364285271L;
+
+ @Id
+ private ObjectId id;
+
+ private Integer iId;
+
+ private Integer authId;
+
+ private String iTitle;
+
+ private Date iPubDate;
+
+ private String iPublisher;
+
+ private String iSubject;
+
+ private String iDesc;
+
+ private Integer iRelated1;
+
+ private Integer iRelated2;
+
+ private Integer iRelated3;
+
+ private Integer iRelated4;
+
+ private Integer iRelated5;
+
+ private String iThumbnail;
+
+ private String iImage;
+
+ private Double iSrp;
+
+ private Double iCost;
+
+ private Date iAvail;
+
+ private Integer iStock;
+
+ private String iIsbn;
+
+ private String iPage;
+
+ private String iBacking;
+
+ private String iDimension;
+
+ private Integer olQty;
+
+ /* for random selection */
+ private double iRandom;
+
+ private String iTitleSoundex;
+
+ public Integer getOlQty()
+ {
+ return olQty;
+ }
+
+ public void setOlQty(Integer olQty)
+ {
+ this.olQty = olQty;
+ }
+
+ public ObjectId getId()
+ {
+ return id;
+ }
+
+ public void setId(ObjectId id)
+ {
+ this.id = id;
+ }
+
+
+ public String getiTitleSoundex()
+ {
+ return iTitleSoundex;
+ }
+
+
+ public void setiTitleSoundex(String iTitleSoundex)
+ {
+ this.iTitleSoundex = iTitleSoundex;
+ }
+
+ @Override
+ public Integer getIId()
+ {
+ return this.iId;
+ }
+
+ @Override
+ public void setIId(Integer IId)
+ {
+ this.iId = IId;
+ }
+
+ @Override
+ public IAuthor getAuthor()
+ {
+ return DatabaseHelper.getDatabase().getAuthorDaoImpl().findById( this.authId );
+ }
+
+ @Override
+ public void setAuthor(IAuthor author)
+ {
+ this.setAuthId( author.getAId() );
+ }
+
+ @Override
+ public String getITitle()
+ {
+ return this.iTitle;
+ }
+
+ @Override
+ public void setITitle(String ITitle)
+ {
+ this.iTitle = ITitle;
+ }
+
+ @Override
+ public Date getIPubDate()
+ {
+ return this.iPubDate;
+ }
+
+ @Override
+ public void setIPubDate(Date IPubDate)
+ {
+ this.iPubDate = IPubDate;
+ }
+
+ @Override
+ public String getIPublisher()
+ {
+ return this.iPublisher;
+ }
+
+ @Override
+ public void setIPublisher(String IPublisher)
+ {
+ this.iPublisher = IPublisher;
+ }
+
+ @Override
+ public String getISubject()
+ {
+ return this.iSubject;
+ }
+
+ @Override
+ public void setISubject(String ISubject)
+ {
+ this.iSubject = ISubject;
+ }
+
+ @Override
+ public String getIDesc()
+ {
+ return this.iDesc;
+ }
+
+ @Override
+ public void setIDesc(String IDesc)
+ {
+ this.iDesc = IDesc;
+ }
+
+ @Override
+ public Integer getIRelated1()
+ {
+ return this.iRelated1;
+ }
+
+ @Override
+ public void setIRelated1(Integer IRelated1)
+ {
+ this.iRelated1 = IRelated1;
+ }
+
+ @Override
+ public Integer getIRelated2()
+ {
+ return this.iRelated2;
+ }
+
+ @Override
+ public void setIRelated2(Integer IRelated2)
+ {
+ this.iRelated2 = IRelated2;
+ }
+
+ @Override
+ public Integer getIRelated3()
+ {
+ return this.iRelated3;
+ }
+
+ @Override
+ public void setIRelated3(Integer IRelated3)
+ {
+ this.iRelated3 = IRelated3;
+ }
+
+ @Override
+ public Integer getIRelated4()
+ {
+ return this.iRelated4;
+ }
+
+ @Override
+ public void setIRelated4(Integer IRelated4)
+ {
+ this.iRelated4 = IRelated4;
+ }
+
+ @Override
+ public Integer getIRelated5()
+ {
+ return this.iRelated5;
+ }
+
+ @Override
+ public void setIRelated5(Integer IRelated5)
+ {
+ this.iRelated5 = IRelated5;
+ }
+
+ @Override
+ public String getIThumbnail()
+ {
+ return this.iThumbnail;
+ }
+
+ @Override
+ public void setIThumbnail(String IThumbnail)
+ {
+ this.iThumbnail = IThumbnail;
+ }
+
+ @Override
+ public String getIImage()
+ {
+ return this.iImage;
+ }
+
+ @Override
+ public void setIImage(String IImage)
+ {
+ this.iImage = IImage;
+ }
+
+ @Override
+ public Double getISrp()
+ {
+ return this.iSrp;
+ }
+
+ @Override
+ public void setISrp(Double i_SRP)
+ {
+ this.iSrp = i_SRP;
+ }
+
+ @Override
+ public Double getICost()
+ {
+ return this.iCost;
+ }
+
+ @Override
+ public void setICost(Double i_COST)
+ {
+ this.iCost = i_COST;
+ }
+
+ @Override
+ public Date getIAvail()
+ {
+ return this.iAvail;
+ }
+
+ @Override
+ public void setIAvail(Date IAvail)
+ {
+ this.iAvail = IAvail;
+ }
+
+ @Override
+ public Integer getIStock()
+ {
+ return this.iStock;
+ }
+
+ @Override
+ public void setIStock(Integer IStock)
+ {
+ this.iStock = IStock;
+ }
+
+ @Override
+ public String getIIsbn()
+ {
+ return this.iIsbn;
+ }
+
+ @Override
+ public void setIIsbn(String IIsbn)
+ {
+ this.iIsbn = IIsbn;
+ }
+
+ @Override
+ public String getIPage()
+ {
+ return this.iPage;
+ }
+
+ @Override
+ public void setIPage(String IPage)
+ {
+ this.iPage = IPage;
+ }
+
+ @Override
+ public String getIBacking()
+ {
+ return this.iBacking;
+ }
+
+ @Override
+ public void setIBacking(String IBacking)
+ {
+ this.iBacking = IBacking;
+ }
+
+ @Override
+ public String getIDimension()
+ {
+ return this.iDimension;
+ }
+
+ @Override
+ public void setIDimension(String IDimension)
+ {
+ this.iDimension = IDimension;
+ }
+
+ @Override
+ public double getIRandom()
+ {
+ return iRandom;
+ }
+
+ @Override
+ public void setIRandom(double iRandom)
+ {
+ this.iRandom = iRandom;
+ }
+
+ public Integer getAuthId()
+ {
+ return authId;
+ }
+
+ public void setAuthId(Integer authId)
+ {
+ this.authId = authId;
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/OrderLine.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/OrderLine.java
new file mode 100644
index 0000000..7714eac
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/OrderLine.java
@@ -0,0 +1,131 @@
+package eu.cloudscale.showcase.db.model.mongo;
+
+import java.io.Serializable;
+
+import org.bson.types.ObjectId;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+import org.springframework.stereotype.Component;
+
+import eu.cloudscale.showcase.db.IService;
+import eu.cloudscale.showcase.db.common.DatabaseHelper;
+import eu.cloudscale.showcase.db.model.IItem;
+import eu.cloudscale.showcase.db.model.IOrderLine;
+import eu.cloudscale.showcase.db.model.IOrders;
+import eu.cloudscale.showcase.db.services.MongoService;
+
+@Component
+@Document( collection = "orderLine")
+public class OrderLine implements IOrderLine, Serializable
+{
+ @Autowired
+ @Qualifier("service")
+ private IService service;
+
+ private static final long serialVersionUID = -6695288937139715783L;
+
+ @Id
+ private ObjectId id;
+
+ private Integer olId;
+
+ private Integer orderId;
+
+ private Integer itemId;
+
+ private Integer olQty;
+
+ private Double olDiscount;
+
+ private String olComment;
+
+
+ public OrderLine()
+ {
+
+ }
+
+ public ObjectId getId()
+ {
+ return id;
+ }
+
+ public void setId(ObjectId id)
+ {
+ this.id = id;
+ }
+
+ @Override
+ public Integer getOlId()
+ {
+ return this.olId;
+ }
+
+ @Override
+ public void setOlId(Integer olId)
+ {
+ this.olId = olId;
+ }
+
+ @Override
+ public IOrders getOrders()
+ {
+ return DatabaseHelper.getDatabase().getOrdersDaoImpl().findById( orderId );
+ }
+
+ @Override
+ public void setOrders(IOrders orders)
+ {
+ this.orderId = orders.getOId();
+ }
+
+ @Override
+ public IItem getItem()
+ {
+ return DatabaseHelper.getDatabase().getItemDaoImpl().findById( this.itemId );
+ }
+
+ @Override
+ public void setItem(IItem item)
+ {
+ this.itemId = item.getIId();
+ }
+
+ @Override
+ public Integer getOlQty()
+ {
+ return this.olQty;
+ }
+
+ @Override
+ public void setOlQty(Integer olQty)
+ {
+ this.olQty = olQty;
+ }
+
+ @Override
+ public Double getOlDiscount()
+ {
+ return this.olDiscount;
+ }
+
+ @Override
+ public void setOlDiscount(Double oL_DISCOUNT)
+ {
+ this.olDiscount = oL_DISCOUNT;
+ }
+
+ @Override
+ public String getOlComment()
+ {
+ return this.olComment;
+ }
+
+ @Override
+ public void setOlComment(String olComment)
+ {
+ this.olComment = olComment;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Orders.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Orders.java
new file mode 100644
index 0000000..0ecd8ed
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/Orders.java
@@ -0,0 +1,213 @@
+package eu.cloudscale.showcase.db.model.mongo;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.bson.types.ObjectId;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+import org.springframework.stereotype.Component;
+
+import eu.cloudscale.showcase.db.IService;
+import eu.cloudscale.showcase.db.common.DatabaseHelper;
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.model.IOrderLine;
+import eu.cloudscale.showcase.db.model.IOrders;
+import eu.cloudscale.showcase.db.services.MongoService;
+
+@Component
+@Document( collection = "orders")
+public class Orders implements IOrders, Serializable
+{
+ @Autowired
+ @Qualifier("service")
+ private IService service;
+
+ private static final long serialVersionUID = -4867580403414098274L;
+
+ @Id
+ private ObjectId id;
+
+ private Integer oId;
+
+ private Integer addressByOShipAddrId;
+
+ private Integer customer;
+
+ private Integer addressByOBillAddrId;
+
+ private Date ODate;
+
+ private Double OSubTotal;
+
+ private Double OTax;
+
+ private Double OTotal;
+
+ private String OShipType;
+
+ private Date OShipDate;
+
+ private String OStatus;
+
+ public Orders()
+ {
+
+ }
+
+ public ObjectId getId()
+ {
+ return id;
+ }
+
+
+ public void setId(ObjectId id)
+ {
+ this.id = id;
+ }
+
+ @Override
+ public Integer getOId()
+ {
+ return this.oId;
+ }
+
+ @Override
+ public void setOId(Integer OId)
+ {
+ this.oId = OId;
+ }
+
+ @Override
+ public IAddress getAddressByOShipAddrId()
+ {
+ return DatabaseHelper.getDatabase().getAddressDaoImpl().findById( this.addressByOShipAddrId );
+ }
+
+ @Override
+ public void setAddressByOShipAddrId(IAddress addressByOShipAddrId)
+ {
+ this.addressByOShipAddrId = addressByOShipAddrId.getAddrId();
+ }
+
+ @Override
+ public ICustomer getCustomer()
+ {
+ return DatabaseHelper.getDatabase().getCustomerDaoImpl().findById( this.customer );
+ }
+
+ @Override
+ public void setCustomer(ICustomer customer)
+ {
+ this.customer = customer.getCId();
+ }
+
+ @Override
+ public IAddress getAddressByOBillAddrId()
+ {
+ return DatabaseHelper.getDatabase().getAddressDaoImpl().findById( this.addressByOBillAddrId );
+ }
+
+ @Override
+ public void setAddressByOBillAddrId(IAddress addressByOBillAddrId)
+ {
+ this.addressByOBillAddrId = addressByOBillAddrId.getAddrId();
+ }
+
+ @Override
+ public Date getODate()
+ {
+ return this.ODate;
+ }
+
+ @Override
+ public void setODate(Date ODate)
+ {
+ this.ODate = ODate;
+ }
+
+ @Override
+ public Double getOSubTotal()
+ {
+ return this.OSubTotal;
+ }
+
+ @Override
+ public void setOSubTotal(Double o_SUB_TOTAL)
+ {
+ this.OSubTotal = o_SUB_TOTAL;
+ }
+
+ @Override
+ public Double getOTax()
+ {
+ return this.OTax;
+ }
+
+ @Override
+ public void setOTax(Double o_TAX)
+ {
+ this.OTax = o_TAX;
+ }
+
+ @Override
+ public Double getOTotal()
+ {
+ return this.OTotal;
+ }
+
+ @Override
+ public void setOTotal(double o_TOTAL)
+ {
+ this.OTotal = o_TOTAL;
+ }
+
+ @Override
+ public String getOShipType()
+ {
+ return this.OShipType;
+ }
+
+ @Override
+ public void setOShipType(String OShipType)
+ {
+ this.OShipType = OShipType;
+ }
+
+ @Override
+ public Date getOShipDate()
+ {
+ return this.OShipDate;
+ }
+
+ @Override
+ public void setOShipDate(Date OShipDate)
+ {
+ this.OShipDate = OShipDate;
+ }
+
+ @Override
+ public String getOStatus()
+ {
+ return this.OStatus;
+ }
+
+ @Override
+ public void setOStatus(String OStatus)
+ {
+ this.OStatus = OStatus;
+ }
+
+ @Override
+ public Set<IOrderLine> getOrderLines()
+ {
+ List ordersList = DatabaseHelper.getDatabase().getOrderLineDaoImpl().findAllByOrder( this );
+ return new HashSet<IOrderLine>();
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/ShoppingCart.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/ShoppingCart.java
new file mode 100644
index 0000000..d86ceee
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/ShoppingCart.java
@@ -0,0 +1,94 @@
+package eu.cloudscale.showcase.db.model.mongo;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.bson.types.ObjectId;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+import org.springframework.stereotype.Component;
+
+import eu.cloudscale.showcase.db.IService;
+import eu.cloudscale.showcase.db.common.DatabaseHelper;
+import eu.cloudscale.showcase.db.model.IShoppingCart;
+import eu.cloudscale.showcase.db.model.IShoppingCartLine;
+import eu.cloudscale.showcase.db.services.MongoService;
+
+@Component
+@Document( collection = "shoppingCart" )
+public class ShoppingCart implements IShoppingCart, Serializable
+{
+
+ @Autowired
+ @Qualifier("service")
+ private IService service;
+
+ private static final long serialVersionUID = -235081098185134853L;
+
+ @Id
+ private ObjectId id;
+
+ private Integer scId;
+
+ private Date scTime;
+
+
+
+ public ShoppingCart()
+ {
+ }
+
+ public ShoppingCart(Date scTime)
+ {
+ this.scTime = scTime;
+ }
+
+ public ObjectId getId()
+ {
+ return id;
+ }
+
+ public void setId(ObjectId id)
+ {
+ this.id = id;
+ }
+
+ @Override
+ public Integer getScId()
+ {
+ return this.scId;
+ }
+
+ @Override
+ public void setScId(Integer scId)
+ {
+ this.scId = scId;
+ }
+
+ @Override
+ public Date getScTime()
+ {
+ return this.scTime;
+ }
+
+ @Override
+ public void setScTime(Date scTime)
+ {
+ this.scTime = scTime;
+ }
+
+ @Override
+ public Set<IShoppingCartLine> getShoppingCartLines()
+ {
+ List res = DatabaseHelper.getDatabase().getShoppingCartDaoImpl().findAllBySC( this );
+ if( res.isEmpty() )
+ return null;
+
+ return new HashSet<IShoppingCartLine>(res);
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/ShoppingCartLine.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/ShoppingCartLine.java
new file mode 100644
index 0000000..dc20938
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/model/mongo/ShoppingCartLine.java
@@ -0,0 +1,103 @@
+package eu.cloudscale.showcase.db.model.mongo;
+
+import java.io.Serializable;
+
+import org.bson.types.ObjectId;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+import org.springframework.stereotype.Component;
+
+import eu.cloudscale.showcase.db.IService;
+import eu.cloudscale.showcase.db.common.DatabaseHelper;
+import eu.cloudscale.showcase.db.model.IItem;
+import eu.cloudscale.showcase.db.model.IShoppingCart;
+import eu.cloudscale.showcase.db.model.IShoppingCartLine;
+import eu.cloudscale.showcase.db.services.MongoService;
+
+@Component
+@Document( collection = "shoppingCartLine" )
+public class ShoppingCartLine implements IShoppingCartLine, Serializable
+{
+ @Autowired
+ @Qualifier("service")
+ private IService service;
+
+ private static final long serialVersionUID = 767045854888711002L;
+
+ @Id
+ private ObjectId id;
+
+ private Integer sclId;
+
+ private Integer item;
+
+ private Integer sclQty;
+
+ private Integer shoppingCart;
+
+ public ShoppingCartLine()
+ {
+ }
+
+
+ public ObjectId getId()
+ {
+ return id;
+ }
+
+ public void setId(ObjectId id)
+ {
+ this.id = id;
+ }
+
+ @Override
+ public IShoppingCart getShoppingCart()
+ {
+ return DatabaseHelper.getDatabase().getShoppingCartDaoImpl().findById( shoppingCart );
+ }
+
+ @Override
+ public void setShoppingCart(IShoppingCart shoppingCart)
+ {
+ this.shoppingCart = shoppingCart.getScId();
+ }
+
+ @Override
+ public Integer getSclId()
+ {
+ return this.sclId;
+ }
+
+ @Override
+ public void setSclId(Integer sclScId)
+ {
+ this.sclId = sclScId;
+ }
+
+ @Override
+ public IItem getItem()
+ {
+ IItem item = DatabaseHelper.getDatabase().getItemDaoImpl().findById( this.item );
+ return item;
+ }
+
+ @Override
+ public void setItem(IItem item)
+ {
+ this.item = item.getIId();
+ }
+
+ @Override
+ public Integer getSclQty()
+ {
+ return this.sclQty;
+ }
+
+ @Override
+ public void setSclQty(Integer sclQty)
+ {
+ this.sclQty = sclQty;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/services/HibernateService.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/services/HibernateService.java
new file mode 100644
index 0000000..6a93070
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/services/HibernateService.java
@@ -0,0 +1,147 @@
+package eu.cloudscale.showcase.db.services;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import eu.cloudscale.showcase.db.AService;
+import eu.cloudscale.showcase.db.dao.IAddressDao;
+import eu.cloudscale.showcase.db.dao.IAuthorDao;
+import eu.cloudscale.showcase.db.dao.ICcXactsDao;
+import eu.cloudscale.showcase.db.dao.ICountryDao;
+import eu.cloudscale.showcase.db.dao.ICustomerDao;
+import eu.cloudscale.showcase.db.dao.IItemDao;
+import eu.cloudscale.showcase.db.dao.IOrderLineDao;
+import eu.cloudscale.showcase.db.dao.IOrdersDao;
+import eu.cloudscale.showcase.db.dao.IShoppingCartDao;
+import eu.cloudscale.showcase.db.dao.IShoppingCartLineDao;
+import eu.cloudscale.showcase.db.model.IItem;
+
+@SuppressWarnings( "unchecked" )
+@Service
+@Transactional(readOnly=true)
+public class HibernateService extends AService
+{
+ @Autowired
+ private IAddressDao addressDao;
+
+ @Autowired
+ private IAuthorDao authorDao;
+
+ @Autowired
+ private ICcXactsDao ccXactsDao;
+
+ @Autowired
+ private ICountryDao countryDao;
+
+ @Autowired
+ private ICustomerDao customerDao;
+
+ @Autowired
+ private IItemDao itemDao;
+
+ @Autowired
+ private IOrderLineDao orderLineDao;
+
+ @Autowired
+ private IOrdersDao ordersDao;
+
+ @Autowired
+ private IShoppingCartDao shoppingCartDao;
+
+ @Autowired
+ private IShoppingCartLineDao shoppingCartLineDao;
+
+ @Override
+ public IAddressDao getAddressDaoImpl()
+ {
+ return addressDao;
+ }
+
+ @Override
+ public IAuthorDao getAuthorDaoImpl()
+ {
+ return authorDao;
+ }
+
+ @Override
+ public ICcXactsDao getCcXactsDaoImpl()
+ {
+ return ccXactsDao;
+ }
+
+ @Override
+ public ICountryDao getCountryDaoImpl()
+ {
+ return countryDao;
+ }
+
+ @Override
+ public ICustomerDao getCustomerDaoImpl()
+ {
+ return customerDao;
+ }
+
+ @Override
+ public IItemDao getItemDaoImpl()
+ {
+ return itemDao;
+ }
+
+ @Override
+ public IOrderLineDao getOrderLineDaoImpl()
+ {
+ return orderLineDao;
+ }
+
+ @Override
+ public IOrdersDao getOrdersDaoImpl()
+ {
+ return ordersDao;
+ }
+
+ @Override
+ public IShoppingCartLineDao getShoppingCartLineDaoImpl()
+ {
+ return shoppingCartLineDao;
+ }
+
+ @Override
+ public IShoppingCartDao getShoppingCartDaoImpl()
+ {
+ return shoppingCartDao;
+ }
+
+ @Override
+ @Cacheable("search")
+ public List<IItem> searchByTitle(String keyword)
+ {
+ IItemDao itemDao = getItemDaoImpl();
+ List<IItem> items = itemDao.findAllByTitle(keyword);
+
+ return items;
+ }
+
+ @Override
+ @Cacheable("search")
+ public List<IItem> searchBySubject(String keyword)
+ {
+ IItemDao itemDao = getItemDaoImpl();
+ List<IItem> items = itemDao.findAllBySubject(keyword);
+
+ return items;
+ }
+
+ @Override
+ @Cacheable( "bestSellers" )
+ public List<Object[]> getBestSellers(String category)
+ {
+ IItemDao itemDao = getItemDaoImpl();
+
+ List<Object[]> res = itemDao.getBestSellers( category );
+ return res;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/services/MongoService.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/services/MongoService.java
new file mode 100644
index 0000000..d8f34ed
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/db/services/MongoService.java
@@ -0,0 +1,209 @@
+package eu.cloudscale.showcase.db.services;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+import eu.cloudscale.showcase.db.AService;
+import eu.cloudscale.showcase.db.dao.IAddressDao;
+import eu.cloudscale.showcase.db.dao.IAuthorDao;
+import eu.cloudscale.showcase.db.dao.ICcXactsDao;
+import eu.cloudscale.showcase.db.dao.ICountryDao;
+import eu.cloudscale.showcase.db.dao.ICustomerDao;
+import eu.cloudscale.showcase.db.dao.IItemDao;
+import eu.cloudscale.showcase.db.dao.IOrderLineDao;
+import eu.cloudscale.showcase.db.dao.IOrdersDao;
+import eu.cloudscale.showcase.db.dao.IShoppingCartDao;
+import eu.cloudscale.showcase.db.dao.IShoppingCartLineDao;
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.model.IItem;
+import eu.cloudscale.showcase.db.model.IOrderLine;
+import eu.cloudscale.showcase.db.model.IOrders;
+import eu.cloudscale.showcase.db.model.IShoppingCart;
+import eu.cloudscale.showcase.db.model.IShoppingCartLine;
+import eu.cloudscale.showcase.db.model.mongo.Item;
+
+@Service
+public class MongoService extends AService
+{
+ @Autowired
+ private IAddressDao addressDao;
+
+ @Autowired
+ private IAuthorDao authorDao;
+
+ @Autowired
+ private ICcXactsDao ccXactsDao;
+
+ @Autowired
+ private ICountryDao countryDao;
+
+ @Autowired
+ private ICustomerDao customerDao;
+
+ @Autowired
+ private IItemDao itemDao;
+
+ @Autowired
+ private IOrderLineDao orderLineDao;
+
+ @Autowired
+ private IOrdersDao ordersDao;
+
+ @Autowired
+ private IShoppingCartDao shoppingCartDao;
+
+ @Autowired
+ private IShoppingCartLineDao shoppingCartLineDao;
+
+ @Override
+ public IAddressDao getAddressDaoImpl()
+ {
+ return addressDao;
+ }
+
+ @Override
+ public IAuthorDao getAuthorDaoImpl()
+ {
+ return authorDao;
+ }
+
+ @Override
+ public ICcXactsDao getCcXactsDaoImpl()
+ {
+ return ccXactsDao;
+ }
+
+ @Override
+ public ICountryDao getCountryDaoImpl()
+ {
+ return countryDao;
+ }
+
+ @Override
+ public ICustomerDao getCustomerDaoImpl()
+ {
+ return customerDao;
+ }
+
+ @Override
+ public IItemDao getItemDaoImpl()
+ {
+ return itemDao;
+ }
+
+ @Override
+ public IOrderLineDao getOrderLineDaoImpl()
+ {
+ return orderLineDao;
+ }
+
+ @Override
+ public IOrdersDao getOrdersDaoImpl()
+ {
+ return ordersDao;
+ }
+
+ @Override
+ public IShoppingCartLineDao getShoppingCartLineDaoImpl()
+ {
+ return shoppingCartLineDao;
+ }
+
+ @Override
+ public IShoppingCartDao getShoppingCartDaoImpl()
+ {
+ return shoppingCartDao;
+ }
+
+ @Override
+ protected IOrders saveOrder(IAddress address, ICustomer customer,
+ String shipping, IShoppingCart sc, double discount)
+ {
+ IItemDao itemDao = getItemDaoImpl();
+ IOrdersDao ordersDao = getOrdersDaoImpl();
+ IOrderLineDao orderLineDao = getOrderLineDaoImpl();
+ Calendar cal = Calendar.getInstance();
+ Random rand = new Random();
+
+ IOrders order = ordersDao.getObject();
+ order.setCustomer( customer );
+ order.setOTax( 8.25 );
+ order.setODate( new Date() );
+ order.setAddressByOBillAddrId( customer.getAddress() );
+ order.setAddressByOShipAddrId( address );
+
+ cal.add( Calendar.DATE, rand.nextInt( 7 ) );
+ order.setOShipDate( cal.getTime() );
+ order.setOShipType( shipping );
+ order.setOStatus( "PENDING" );
+ order.setOTotal( calculateTotal( sc ) );
+ // TODO: order.setOSubTotal( calculateSubTotal(sc) );
+
+ order.setOSubTotal( calculateTotal( sc ) );
+ ordersDao.shrani( order );
+
+ Set<IShoppingCartLine> res = sc.getShoppingCartLines();
+
+ if( res != null && !res.isEmpty() )
+ {
+ for ( IShoppingCartLine scl : res)
+ {
+ IOrderLine ol = orderLineDao.getObject();
+ ol.setItem( scl.getItem() );
+ ol.setOlComment( getRandomString( 20, 100 ) );
+ ol.setOlDiscount( discount );
+ ol.setOlQty( scl.getSclQty() );
+ ol.setOrders( order );
+ order.getOrderLines().add( ol );
+ orderLineDao.shrani( ol );
+
+ Item item = (Item) itemDao.findById( scl.getItem().getIId() );
+ Integer olQty = item.getOlQty();
+ item.setOlQty( (olQty == null ? 0 : olQty ) + 1 );
+ itemDao.shrani( item );
+
+ // TODO: Update item IStock property
+ }
+ }
+
+ ordersDao.shrani( order );
+
+ return order;
+ }
+
+ @Override
+ @Cacheable("search")
+ public List<IItem> searchByTitle(String keyword)
+ {
+ IItemDao itemDao = getItemDaoImpl();
+ List<IItem> items = itemDao.findAllByTitle( keyword );
+
+ return items;
+ }
+
+ @Override
+ @Cacheable("search")
+ public List<IItem> searchBySubject(String keyword)
+ {
+ IItemDao itemDao = getItemDaoImpl();
+ List<IItem> items = itemDao.findAllBySubject( keyword );
+
+ return items;
+ }
+
+ @Override
+ @Cacheable("bestSellers")
+ public List<Object[]> getBestSellers(String category)
+ {
+ IItemDao itemDao = getItemDaoImpl();
+ return itemDao.getBestSellers( category );
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/AGenerate.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/AGenerate.java
new file mode 100644
index 0000000..4802499
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/AGenerate.java
@@ -0,0 +1,607 @@
+package eu.cloudscale.showcase.generate;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.Random;
+
+import org.springframework.context.support.GenericXmlApplicationContext;
+import org.springframework.transaction.annotation.Transactional;
+
+import eu.cloudscale.showcase.db.IService;
+import eu.cloudscale.showcase.db.common.ContextHelper;
+import eu.cloudscale.showcase.db.common.DatabaseHelper;
+import eu.cloudscale.showcase.db.dao.IAddressDao;
+import eu.cloudscale.showcase.db.dao.IAuthorDao;
+import eu.cloudscale.showcase.db.dao.ICountryDao;
+import eu.cloudscale.showcase.db.dao.ICustomerDao;
+import eu.cloudscale.showcase.db.dao.IItemDao;
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.IAuthor;
+import eu.cloudscale.showcase.db.model.ICountry;
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.model.IItem;
+import eu.cloudscale.showcase.db.services.MongoService;
+
+
+public abstract class AGenerate implements IGenerate
+{
+
+ // TODO: Move this to properties file
+ protected static final int NUM_EBS = 100;
+
+ // TODO: Move this to properties file
+ protected static final int NUM_ITEMS = 10000;
+
+ // TODO: Move this to properties file
+ protected static final int NUM_CUSTOMERS = NUM_EBS * 2880;
+
+ // TODO: Move this to properties file
+ protected static final int NUM_ADDRESSES = 2 * NUM_CUSTOMERS;
+
+ // TODO: Move this to properties file
+ protected static final int NUM_AUTHORS = (int) ( .25 * NUM_ITEMS );
+
+ // TODO: Move this to properties file
+ protected static final int NUM_ORDERS = (int) ( .9 * NUM_CUSTOMERS );
+
+ // TODO: Move this to properties file
+ protected static String[][] tables = {
+ {"address", "addr_co_id", "addr_zip" }, {"author", "a_lname" },
+ {"cc_xacts" }, {"country", "co_name" },
+ {"customer", "c_addr_id", "c_uname" },
+ {"item", "i_title", "i_subject", "i_a_id" },
+ {"order_line", "ol_i_id", "ol_o_id" }, {"orders", "o_c_id" },
+ {"shopping_cart" }, {"shopping_cart_line", "scl_i_id" } };
+
+ protected Random rand = new Random();
+
+ protected GenericXmlApplicationContext ctx = null;
+
+ protected IService db = null;
+
+ public AGenerate()
+ {
+ ctx = ContextHelper.getApplicationContext();
+ db = DatabaseHelper.getDatabase();
+ }
+
+
+ protected String getRandomAString(int min, int max)
+ {
+ String newstring = new String();
+ int i;
+ final char[] chars = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', '#', '$', '%', '^',
+ '&', '*', '(', ')', '_', '-', '=', '+', '{', '}', '[', ']',
+ '|', ':', ';', ',', '.', '?', '/', '~', ' ' }; // 79 characters
+ int strlen = (int) Math
+ .floor( rand.nextDouble() * ( ( max - min ) + 1 ) );
+ strlen += min;
+ for ( i = 0; i < strlen; i++ )
+ {
+ char c = chars[(int) Math.floor( rand.nextDouble() * 79 )];
+ newstring = newstring.concat( String.valueOf( c ) );
+ }
+ return newstring;
+ }
+
+ protected String getRandomAString(int length)
+ {
+ String newstring = new String();
+ int i;
+ final char[] chars = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+ 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', '#', '$', '%', '^',
+ '&', '*', '(', ')', '_', '-', '=', '+', '{', '}', '[', ']',
+ '|', ':', ';', ',', '.', '?', '/', '~', ' ' }; // 79 characters
+ for ( i = 0; i < length; i++ )
+ {
+ char c = chars[(int) Math.floor( rand.nextDouble() * 79 )];
+ newstring = newstring.concat( String.valueOf( c ) );
+ }
+ return newstring;
+ }
+
+ protected int getRandomNString(int num_digits)
+ {
+ int return_num = 0;
+ for ( int i = 0; i < num_digits; i++ )
+ {
+ return_num += getRandomInt( 0, 9 )
+ * (int) java.lang.Math.pow( 10.0, (double) i );
+ }
+ return return_num;
+ }
+
+ protected int getRandomNString(int min, int max)
+ {
+ int strlen = (int) Math
+ .floor( rand.nextDouble() * ( ( max - min ) + 1 ) ) + min;
+ return getRandomNString( strlen );
+ }
+
+ protected int getRandomInt(int lower, int upper)
+ {
+
+ int num = (int) Math.floor( rand.nextDouble()
+ * ( ( upper + 1 ) - lower ) );
+ if ( num + lower > upper || num + lower < lower )
+ {
+ System.out.println( "ERROR: Random returned value of of range!" );
+ System.exit( 1 );
+ }
+ return num + lower;
+ }
+
+ protected String DigSyl(int D, int N)
+ {
+ int i;
+ String resultString = new String();
+ String Dstr = Integer.toString( D );
+
+ if ( N > Dstr.length() )
+ {
+ int padding = N - Dstr.length();
+ for ( i = 0; i < padding; i++ )
+ resultString = resultString.concat( "BA" );
+ }
+
+ for ( i = 0; i < Dstr.length(); i++ )
+ {
+ if ( Dstr.charAt( i ) == '0' )
+ resultString = resultString.concat( "BA" );
+ else if ( Dstr.charAt( i ) == '1' )
+ resultString = resultString.concat( "OG" );
+ else if ( Dstr.charAt( i ) == '2' )
+ resultString = resultString.concat( "AL" );
+ else if ( Dstr.charAt( i ) == '3' )
+ resultString = resultString.concat( "RI" );
+ else if ( Dstr.charAt( i ) == '4' )
+ resultString = resultString.concat( "RE" );
+ else if ( Dstr.charAt( i ) == '5' )
+ resultString = resultString.concat( "SE" );
+ else if ( Dstr.charAt( i ) == '6' )
+ resultString = resultString.concat( "AT" );
+ else if ( Dstr.charAt( i ) == '7' )
+ resultString = resultString.concat( "UL" );
+ else if ( Dstr.charAt( i ) == '8' )
+ resultString = resultString.concat( "IN" );
+ else if ( Dstr.charAt( i ) == '9' )
+ resultString = resultString.concat( "NG" );
+ }
+
+ return resultString;
+ }
+
+ @Override
+ @Transactional(readOnly=false)
+ public void populateCountryTable()
+ {
+ String[] countries = {"United States", "United Kingdom", "Canada",
+ "Germany", "France", "Japan", "Netherlands", "Italy",
+ "Switzerland", "Australia", "Algeria", "Argentina", "Armenia",
+ "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangla Desh",
+ "Barbados", "Belarus", "Belgium", "Bermuda", "Bolivia",
+ "Botswana", "Brazil", "Bulgaria", "Cayman Islands", "Chad",
+ "Chile", "China", "Christmas Island", "Colombia", "Croatia",
+ "Cuba", "Cyprus", "Czech Republic", "Denmark",
+ "Dominican Republic", "Eastern Caribbean", "Ecuador", "Egypt",
+ "El Salvador", "Estonia", "Ethiopia", "Falkland Island",
+ "Faroe Island", "Fiji", "Finland", "Gabon", "Gibraltar",
+ "Greece", "Guam", "Hong Kong", "Hungary", "Iceland", "India",
+ "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Jamaica",
+ "Jordan", "Kazakhstan", "Kuwait", "Lebanon", "Luxembourg",
+ "Malaysia", "Mexico", "Mauritius", "New Zealand", "Norway",
+ "Pakistan", "Philippines", "Poland", "Portugal", "Romania",
+ "Russia", "Saudi Arabia", "Singapore", "Slovakia",
+ "South Africa", "South Korea", "Spain", "Sudan", "Sweden",
+ "Taiwan", "Thailand", "Trinidad", "Turkey", "Venezuela",
+ "Zambia" };
+
+ double[] exchanges = {1, .625461, 1.46712, 1.86125, 6.24238, 121.907,
+ 2.09715, 1842.64, 1.51645, 1.54208, 65.3851, 0.998, 540.92,
+ 13.0949, 3977, 1, .3757, 48.65, 2, 248000, 38.3892, 1, 5.74,
+ 4.7304, 1.71, 1846, .8282, 627.1999, 494.2, 8.278, 1.5391,
+ 1677, 7.3044, 23, .543, 36.0127, 7.0707, 15.8, 2.7, 9600,
+ 3.33771, 8.7, 14.9912, 7.7, .6255, 7.124, 1.9724, 5.65822,
+ 627.1999, .6255, 309.214, 1, 7.75473, 237.23, 74.147, 42.75,
+ 8100, 3000, .3083, .749481, 4.12, 37.4, 0.708, 150, .3062,
+ 1502, 38.3892, 3.8, 9.6287, 25.245, 1.87539, 7.83101, 52,
+ 37.8501, 3.9525, 190.788, 15180.2, 24.43, 3.7501, 1.72929,
+ 43.9642, 6.25845, 1190.15, 158.34, 5.282, 8.54477, 32.77,
+ 37.1414, 6.1764, 401500, 596, 2447.7 };
+
+ String[] currencies = {"Dollars", "Pounds", "Dollars",
+ "Deutsche Marks", "Francs", "Yen", "Guilders", "Lira",
+ "Francs", "Dollars", "Dinars", "Pesos", "Dram", "Schillings",
+ "Manat", "Dollars", "Dinar", "Taka", "Dollars", "Rouble",
+ "Francs", "Dollars", "Boliviano", "Pula", "Real", "Lev",
+ "Dollars", "Franc", "Pesos", "Yuan Renmimbi", "Dollars",
+ "Pesos", "Kuna", "Pesos", "Pounds", "Koruna", "Kroner",
+ "Pesos", "Dollars", "Sucre", "Pounds", "Colon", "Kroon",
+ "Birr", "Pound", "Krone", "Dollars", "Markka", "Franc",
+ "Pound", "Drachmas", "Dollars", "Dollars", "Forint", "Krona",
+ "Rupees", "Rupiah", "Rial", "Dinar", "Punt", "Shekels",
+ "Dollars", "Dinar", "Tenge", "Dinar", "Pounds", "Francs",
+ "Ringgit", "Pesos", "Rupees", "Dollars", "Kroner", "Rupees",
+ "Pesos", "Zloty", "Escudo", "Leu", "Rubles", "Riyal",
+ "Dollars", "Koruna", "Rand", "Won", "Pesetas", "Dinar",
+ "Krona", "Dollars", "Baht", "Dollars", "Lira", "Bolivar",
+ "Kwacha" };
+
+ int NUM_COUNTRIES = 92;
+
+ System.out.println( "Populating COUNTRY with " + NUM_COUNTRIES
+ + " countries" );
+
+ ICountryDao countryDao = db.getCountryDaoImpl();
+ countryDao.createTable();
+
+ for ( int i = 1; i <= NUM_COUNTRIES; i++ )
+ {
+ ICountry c = countryDao.getObject();
+
+ if( db instanceof MongoService)
+ {
+ c.setCoId( i );
+ }
+ c.setCoName( countries[i - 1] );
+ c.setCoExchange( exchanges[i - 1] );
+ c.setCoCurrency( currencies[i - 1] );
+
+ countryDao.shrani( c );
+ }
+
+ countryDao.finish();
+
+ //System.out.println( "" );
+ }
+
+
+ @Override
+ public void populateAuthorTable()
+ {
+ String A_FNAME, A_MNAME, A_LNAME, A_BIO;
+ java.sql.Date A_DOB;
+ GregorianCalendar cal;
+
+ System.out.println( "Populating AUTHOR Table with " + NUM_AUTHORS
+ + " authors" );
+
+ IAuthorDao authorDao = db.getAuthorDaoImpl();
+
+ for ( int i = 1; i <= NUM_AUTHORS; i++ )
+ {
+ IAuthor a = authorDao.getObject();
+
+ int month, day, year, maxday;
+ A_FNAME = getRandomAString( 3, 20 );
+ A_MNAME = getRandomAString( 1, 20 );
+ A_LNAME = getRandomAString( 1, 20 );
+ year = getRandomInt( 1800, 1990 );
+ month = getRandomInt( 0, 11 );
+ maxday = 31;
+ if ( month == 3 | month == 5 | month == 8 | month == 10 )
+ maxday = 30;
+ else if ( month == 1 )
+ maxday = 28;
+ day = getRandomInt( 1, maxday );
+ cal = new GregorianCalendar( year, month, day );
+ A_DOB = new java.sql.Date( cal.getTime().getTime() );
+ A_BIO = getRandomAString( 125, 500 );
+
+ // MongoDB doesn't have autoincrement field so we must set ID manually
+ if( db instanceof MongoService)
+ {
+ a.setAId( i );
+ }
+ a.setAFname( A_FNAME );
+ a.setALname( A_LNAME );
+ a.setAMname( A_MNAME );
+ a.setADob( A_DOB );
+ a.setABio( A_BIO );
+
+ authorDao.shrani( a );
+ }
+
+ authorDao.finish();
+
+ System.out.println( "" );
+ }
+
+
+ @Override
+ public void populateAddressTable()
+ {
+ System.out.println( "Populating ADDRESS Table with " + NUM_ADDRESSES
+ + " addresses" );
+ System.out.print( "Complete (in 10,000's): " );
+ String ADDR_STREET1, ADDR_STREET2, ADDR_CITY, ADDR_STATE;
+ String ADDR_ZIP;
+ int ADDR_CO_ID;
+
+ IAddressDao addressDao = db.getAddressDaoImpl();
+ ICountryDao countryDao = db.getCountryDaoImpl();
+
+ for ( int i = 1; i <= NUM_ADDRESSES; i++ )
+ {
+ IAddress a = addressDao.getObject();
+
+ if ( i % 10000 == 0 )
+ System.out.print( i / 10000 + " " );
+
+ ADDR_STREET1 = getRandomAString( 15, 40 );
+ ADDR_STREET2 = getRandomAString( 15, 40 );
+ ADDR_CITY = getRandomAString( 4, 30 );
+ ADDR_STATE = getRandomAString( 2, 20 );
+ ADDR_ZIP = getRandomAString( 5, 10 );
+ ADDR_CO_ID = getRandomInt( 1, 92 );
+
+ // MongoDB doesn't have autoincrement field so we must set ID manually
+ if( db instanceof MongoService)
+ {
+ a.setAddrId( i );
+ }
+ a.setAddrStreet1( ADDR_STREET1 );
+ a.setAddrStreet2( ADDR_STREET2 );
+ a.setAddrCity( ADDR_CITY );
+ a.setAddrState( ADDR_STATE );
+ a.setAddrZip( ADDR_ZIP );
+ a.setCountry( countryDao.findById( ADDR_CO_ID ) );
+
+ addressDao.shrani( a );
+ }
+
+ addressDao.finish();
+
+ System.out.println( "" );
+ }
+
+
+ @Override
+ public void populateCustomerTable()
+ {
+ String C_UNAME, C_PASSWD, C_LNAME, C_FNAME;
+ int C_ADDR_ID, C_PHONE;
+ String C_EMAIL;
+ java.sql.Date C_SINCE, C_LAST_LOGIN;
+ java.sql.Timestamp C_LOGIN, C_EXPIRATION;
+ double C_DISCOUNT, C_BALANCE, C_YTD_PMT;
+ java.sql.Date C_BIRTHDATE;
+ String C_DATA;
+ int i;
+
+ System.out.println( "Populating CUSTOMER Table with " + NUM_CUSTOMERS
+ + " customers" );
+ System.out.print( "Complete (in 10,000's): " );
+
+ ICustomerDao customerDao = db.getCustomerDaoImpl();
+ IAddressDao addressDao = db.getAddressDaoImpl();
+
+ for ( i = 1; i <= NUM_CUSTOMERS; i++ )
+ {
+ ICustomer c = customerDao.getObject();
+
+ if ( i % 10000 == 0 )
+ System.out.print( i / 10000 + " " );
+
+ C_UNAME = DigSyl( i, 0 ).toLowerCase();
+ C_PASSWD = C_UNAME.toLowerCase();
+ C_LNAME = getRandomAString( 8, 15 );
+ C_FNAME = getRandomAString( 8, 15 );
+ C_ADDR_ID = getRandomInt( 1, NUM_ADDRESSES );
+ C_PHONE = getRandomNString( 9, 16 );
+ C_EMAIL = C_UNAME + "@" + getRandomAString( 2, 9 ) + ".com";
+
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.add( Calendar.DAY_OF_YEAR, -1 * getRandomInt( 1, 730 ) );
+ C_SINCE = new java.sql.Date( cal.getTime().getTime() );
+ cal.add( Calendar.DAY_OF_YEAR, getRandomInt( 0, 60 ) );
+ if ( cal.after( new GregorianCalendar() ) )
+ cal = new GregorianCalendar();
+
+ C_LAST_LOGIN = new java.sql.Date( cal.getTime().getTime() );
+ C_LOGIN = new java.sql.Timestamp( System.currentTimeMillis() );
+ cal = new GregorianCalendar();
+ cal.add( Calendar.HOUR, 2 );
+ C_EXPIRATION = new java.sql.Timestamp( cal.getTime().getTime() );
+
+ C_DISCOUNT = (double) getRandomInt( 0, 50 ) / 100.0;
+ C_BALANCE = 0.00;
+ C_YTD_PMT = (double) getRandomInt( 0, 99999 ) / 100.0;
+ int year = getRandomInt( 1880, 2000 );
+ int month = getRandomInt( 0, 11 );
+ int maxday = 31;
+ int day;
+ if ( month == 3 | month == 5 | month == 8 | month == 10 )
+ maxday = 30;
+ else if ( month == 1 )
+ maxday = 28;
+ day = getRandomInt( 1, maxday );
+ cal = new GregorianCalendar( year, month, day );
+ C_BIRTHDATE = new java.sql.Date( cal.getTime().getTime() );
+
+ C_DATA = getRandomAString( 100, 500 );
+
+ // MongoDB doesn't have autoincrement field so we must set ID manually
+ if( db instanceof MongoService)
+ {
+ c.setCId( i );
+ }
+ c.setCUname( C_UNAME );
+ c.setCPasswd( C_PASSWD );
+ c.setCFname( C_FNAME );
+ c.setCLname( C_LNAME );
+ IAddress addr = addressDao.findById( C_ADDR_ID );
+ c.setAddress( addr );
+ c.setCPhone( String.valueOf( C_PHONE ) );
+ c.setCEmail( C_EMAIL );
+ c.setCSince( C_SINCE );
+ c.setCLastVisit( C_LAST_LOGIN );
+ c.setCLogin( C_LOGIN );
+ c.setCExpiration( C_EXPIRATION );
+ c.setCDiscount( C_DISCOUNT );
+ c.setCBalance( C_BALANCE );
+ c.setCYtdPmt( C_YTD_PMT );
+ c.setCBirthdate( C_BIRTHDATE );
+ c.setCData( C_DATA );
+
+ customerDao.shrani( c );
+ }
+
+ customerDao.finish();
+
+ //System.out.print( "\n" );
+ }
+
+
+ @Override
+ public void populateItemTable()
+ {
+ String I_TITLE;
+ GregorianCalendar cal;
+ int I_A_ID;
+ java.sql.Date I_PUB_DATE;
+ String I_PUBLISHER, I_SUBJECT, I_DESC;
+ int I_RELATED1, I_RELATED2, I_RELATED3, I_RELATED4, I_RELATED5;
+ String I_THUMBNAIL, I_IMAGE;
+ double I_SRP, I_COST, I_RANDOM;
+ java.sql.Date I_AVAIL;
+ int I_STOCK;
+ String I_ISBN;
+ int I_PAGE;
+ String I_BACKING;
+ String I_DIMENSIONS;
+
+ String[] SUBJECTS = {"ARTS", "BIOGRAPHIES", "BUSINESS", "CHILDREN",
+ "COMPUTERS", "COOKING", "HEALTH", "HISTORY", "HOME", "HUMOR",
+ "LITERATURE", "MYSTERY", "NON-FICTION", "PARENTING",
+ "POLITICS", "REFERENCE", "RELIGION", "ROMANCE", "SELF-HELP",
+ "SCIENCE-NATURE", "SCIENCE-FICTION", "SPORTS", "YOUTH",
+ "TRAVEL" };
+ int NUM_SUBJECTS = 24;
+
+ String[] BACKINGS = {"HARDBACK", "PAPERBACK", "USED", "AUDIO",
+ "LIMITED-EDITION" };
+ int NUM_BACKINGS = 5;
+
+ System.out.println( "Populating ITEM table with " + NUM_ITEMS
+ + " items" );
+
+ IItemDao itemDao = db.getItemDaoImpl();
+ IAuthorDao authorDao = db.getAuthorDaoImpl();
+
+ Random rand = new Random();
+
+ for ( int i = 1; i <= NUM_ITEMS; i++ )
+ {
+ I_RANDOM = rand.nextDouble();
+ int month, day, year, maxday;
+ I_TITLE = getRandomAString( 14, 60 );
+ if ( i <= ( NUM_ITEMS / 4 ) )
+ I_A_ID = i;
+ else
+ I_A_ID = getRandomInt( 1, NUM_ITEMS / 4 );
+
+ year = getRandomInt( 1930, 2000 );
+ month = getRandomInt( 0, 11 );
+ maxday = 31;
+ if ( month == 3 | month == 5 | month == 8 | month == 10 )
+ maxday = 30;
+ else if ( month == 1 )
+ maxday = 28;
+ day = getRandomInt( 1, maxday );
+ cal = new GregorianCalendar( year, month, day );
+ I_PUB_DATE = new java.sql.Date( cal.getTime().getTime() );
+
+ I_PUBLISHER = getRandomAString( 14, 60 );
+ I_SUBJECT = SUBJECTS[getRandomInt( 0, NUM_SUBJECTS - 1 )];
+ I_DESC = getRandomAString( 100, 500 );
+
+ I_RELATED1 = getRandomInt( 1, NUM_ITEMS );
+ do
+ {
+ I_RELATED2 = getRandomInt( 1, NUM_ITEMS );
+ }
+ while ( I_RELATED2 == I_RELATED1 );
+ do
+ {
+ I_RELATED3 = getRandomInt( 1, NUM_ITEMS );
+ }
+ while ( I_RELATED3 == I_RELATED1 || I_RELATED3 == I_RELATED2 );
+ do
+ {
+ I_RELATED4 = getRandomInt( 1, NUM_ITEMS );
+ }
+ while ( I_RELATED4 == I_RELATED1 || I_RELATED4 == I_RELATED2
+ || I_RELATED4 == I_RELATED3 );
+ do
+ {
+ I_RELATED5 = getRandomInt( 1, NUM_ITEMS );
+ }
+ while ( I_RELATED5 == I_RELATED1 || I_RELATED5 == I_RELATED2
+ || I_RELATED5 == I_RELATED3 || I_RELATED5 == I_RELATED4 );
+
+ I_THUMBNAIL = new String( "img" + i % 100 + "/thumb_" + i + ".gif" );
+ I_IMAGE = new String( "img" + i % 100 + "/image_" + i + ".gif" );
+ I_SRP = (double) getRandomInt( 100, 99999 );
+ I_SRP /= 100.0;
+
+ I_COST = I_SRP
+ - ( ( ( (double) getRandomInt( 0, 50 ) / 100.0 ) ) * I_SRP );
+
+ cal.add( Calendar.DAY_OF_YEAR, getRandomInt( 1, 30 ) );
+ I_AVAIL = new java.sql.Date( cal.getTime().getTime() );
+ I_STOCK = getRandomInt( 10, 30 );
+ I_ISBN = getRandomAString( 13 );
+ I_PAGE = getRandomInt( 20, 9999 );
+ I_BACKING = BACKINGS[getRandomInt( 0, NUM_BACKINGS - 1 )];
+ I_DIMENSIONS = ( (double) getRandomInt( 1, 9999 ) / 100.0 ) + "x"
+ + ( (double) getRandomInt( 1, 9999 ) / 100.0 ) + "x"
+ + ( (double) getRandomInt( 1, 9999 ) / 100.0 );
+
+ IItem item = itemDao.getObject();
+ // Set parameter
+ // MongoDB doesn't have autoincrement field so we must set ID manually
+ if( db instanceof MongoService)
+ {
+ item.setIId( i );
+ }
+ item.setIRandom( I_RANDOM );
+ item.setITitle( I_TITLE );
+ item.setIPubDate( I_PUB_DATE );
+ item.setIPublisher( I_PUBLISHER );
+ item.setISubject( I_SUBJECT );
+ item.setIDesc( I_DESC );
+ item.setIRelated1( I_RELATED1 );
+ item.setIRelated2( I_RELATED2 );
+ item.setIRelated3( I_RELATED3 );
+ item.setIRelated4( I_RELATED4 );
+ item.setIRelated5( I_RELATED5 );
+ item.setIThumbnail( I_THUMBNAIL );
+ item.setIImage( I_IMAGE );
+ item.setISrp( I_SRP );
+ item.setICost( I_COST );
+ item.setIAvail( I_AVAIL );
+ item.setIStock( I_STOCK );
+ item.setIIsbn( I_ISBN );
+ item.setIPage( String.valueOf( I_PAGE ) );
+ item.setIBacking( I_BACKING );
+ item.setIDimension( I_DIMENSIONS );
+ item.setAuthor( authorDao.findById( I_A_ID ) );
+
+ itemDao.shrani( item );
+
+ itemDao.findById( item.getIId() );
+ }
+
+ itemDao.finish();
+ //System.out.println( "" );
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/Generate.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/Generate.java
new file mode 100644
index 0000000..5b173d0
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/Generate.java
@@ -0,0 +1,71 @@
+package eu.cloudscale.showcase.generate;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PropertiesLoaderUtils;
+
+import eu.cloudscale.showcase.db.common.DatabaseHelper;
+
+public class Generate
+{
+
+ private IGenerate db;
+
+ public Generate(String dbType)
+ {
+
+// Resource resource = new ClassPathResource( "database.properties" );
+// Properties prop = null;
+// try
+// {
+// prop = PropertiesLoaderUtils.loadProperties( resource );
+// }
+// catch ( IOException e )
+// {
+// e.printStackTrace();
+// }
+//
+// String dbType = prop.getProperty( "jdbc.dbtype" );
+
+ if ( dbType.equalsIgnoreCase( "mongo" )
+ || dbType.equalsIgnoreCase( "mongodb" ) )
+ {
+ db = new GenerateMongo();
+ }
+ else
+ {
+ DatabaseHelper.loadMySQLDriver();
+ db = new GenerateHibernate();
+ }
+
+ }
+
+ public void generate()
+ {
+
+ //db.dropTables( tables );
+ db.populateCountryTable();
+ db.populateAuthorTable();
+ db.populateAddressTable();
+ db.populateCustomerTable();
+ db.populateItemTable();
+ db.populateOrdersAndCC_XACTSTable();
+ // db.createIndexes(tables);
+
+ System.out.println( "FINISHED!" );
+ }
+
+ public static void main(String[] args)
+ {
+ if( args.length < 1 )
+ {
+ System.out.println("Usage: $ java Generate <mysql|mongodb>");
+ System.exit(0);
+ }
+ Generate generate = new Generate(args[0]);
+ generate.generate();
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/GenerateHibernate.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/GenerateHibernate.java
new file mode 100644
index 0000000..82b1110
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/GenerateHibernate.java
@@ -0,0 +1,169 @@
+package eu.cloudscale.showcase.generate;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashSet;
+
+import eu.cloudscale.showcase.db.dao.IAddressDao;
+import eu.cloudscale.showcase.db.dao.IAuthorDao;
+import eu.cloudscale.showcase.db.dao.ICcXactsDao;
+import eu.cloudscale.showcase.db.dao.ICountryDao;
+import eu.cloudscale.showcase.db.dao.ICustomerDao;
+import eu.cloudscale.showcase.db.dao.IItemDao;
+import eu.cloudscale.showcase.db.dao.IOrderLineDao;
+import eu.cloudscale.showcase.db.dao.IOrdersDao;
+import eu.cloudscale.showcase.db.dao.hibernate.impl.AuthorDaoImpl;
+import eu.cloudscale.showcase.db.model.ICcXacts;
+import eu.cloudscale.showcase.db.model.IOrderLine;
+import eu.cloudscale.showcase.db.model.hibernate.CcXacts;
+import eu.cloudscale.showcase.db.model.hibernate.OrderLine;
+import eu.cloudscale.showcase.db.model.hibernate.Orders;
+
+
+public class GenerateHibernate extends AGenerate
+{
+
+ public GenerateHibernate()
+ {
+ super();
+ }
+
+ @Override
+ public void populateOrdersAndCC_XACTSTable()
+ {
+ GregorianCalendar cal;
+ String[] credit_cards = {"VISA", "MASTERCARD", "DISCOVER", "AMEX",
+ "DINERS" };
+ int num_card_types = 5;
+ String[] ship_types = {"AIR", "UPS", "FEDEX", "SHIP", "COURIER", "MAIL" };
+ int num_ship_types = 6;
+
+ String[] status_types = {"PROCESSING", "SHIPPED", "PENDING", "DENIED" };
+ int num_status_types = 4;
+
+ // Order variables
+ int O_C_ID;
+ java.sql.Timestamp O_DATE;
+ double O_SUB_TOTAL;
+ double O_TAX;
+ double O_TOTAL;
+ String O_SHIP_TYPE;
+ java.sql.Timestamp O_SHIP_DATE;
+ int O_BILL_ADDR_ID, O_SHIP_ADDR_ID;
+ String O_STATUS;
+
+ String CX_TYPE;
+ int CX_NUM;
+ String CX_NAME;
+ java.sql.Date CX_EXPIRY;
+ int CX_AUTH_ID;
+ int CX_CO_ID;
+
+ System.out.println( "Populating ORDERS, ORDER_LINES, CC_XACTS with "
+ + NUM_ORDERS + " orders" );
+
+ System.out.print( "Complete (in 10,000's): " );
+
+ ICustomerDao customerDao = super.db.getCustomerDaoImpl();
+ IAddressDao addressDao = super.db.getAddressDaoImpl();
+ IItemDao itemDao = super.db.getItemDaoImpl();
+ ICountryDao countryDao = super.db.getCountryDaoImpl();
+ IOrdersDao ordersDao = super.db.getOrdersDaoImpl();
+ IOrderLineDao orderLineDao = super.db.getOrderLineDaoImpl();
+ ICcXactsDao ccXactsDao = super.db.getCcXactsDaoImpl();
+ IAuthorDao authorDao = super.db.getAuthorDaoImpl();
+
+ for ( int i = 1; i <= NUM_ORDERS; i++ )
+ {
+ if ( i % 10000 == 0 )
+ System.out.print( i / 10000 + " " );
+
+ int num_items = getRandomInt( 1, 5 );
+ O_C_ID = getRandomInt( 1, NUM_CUSTOMERS );
+ cal = new GregorianCalendar();
+ cal.add( Calendar.DAY_OF_YEAR, -1 * getRandomInt( 1, 60 ) );
+ O_DATE = new java.sql.Timestamp( cal.getTime().getTime() );
+ O_SUB_TOTAL = (double) getRandomInt( 1000, 999999 ) / 100;
+ O_TAX = O_SUB_TOTAL * 0.0825;
+ O_TOTAL = O_SUB_TOTAL + O_TAX + 3.00 + num_items;
+ O_SHIP_TYPE = ship_types[getRandomInt( 0, num_ship_types - 1 )];
+ cal.add( Calendar.DAY_OF_YEAR, getRandomInt( 0, 7 ) );
+ O_SHIP_DATE = new java.sql.Timestamp( cal.getTime().getTime() );
+
+ O_BILL_ADDR_ID = getRandomInt( 1, 2 * NUM_CUSTOMERS );
+ O_SHIP_ADDR_ID = getRandomInt( 1, 2 * NUM_CUSTOMERS );
+ O_STATUS = status_types[getRandomInt( 0, num_status_types - 1 )];
+
+ Orders order = new Orders();
+
+ // Set parameter
+ order.setCustomer( customerDao.findById( O_C_ID ) );
+ order.setODate( new Date( O_DATE.getTime() ) );
+ order.setOSubTotal( O_SUB_TOTAL );
+ order.setOTax( O_TAX );
+ order.setOTotal( O_TOTAL );
+ order.setOShipType( O_SHIP_TYPE );
+ order.setOShipDate( O_SHIP_DATE );
+ order.setAddressByOBillAddrId( addressDao.findById( O_BILL_ADDR_ID ) );
+ order.setAddressByOShipAddrId( addressDao.findById( O_SHIP_ADDR_ID ) );
+ order.setOStatus( O_STATUS );
+ order.setCcXactses( new HashSet<ICcXacts>() );
+ order.setOrderLines( new HashSet<IOrderLine>() );
+ ordersDao.shrani( order );
+
+ for ( int j = 1; j <= num_items; j++ )
+ {
+ int OL_ID = j;
+ int OL_O_ID = i;
+ int OL_I_ID = getRandomInt( 1, NUM_ITEMS );
+ int OL_QTY = getRandomInt( 1, 300 );
+ double OL_DISCOUNT = (double) getRandomInt( 0, 30 ) / 100;
+ String OL_COMMENTS = getRandomAString( 20, 100 );
+
+ OrderLine orderLine = new OrderLine();
+ orderLine.setItem( itemDao.findById( OL_I_ID ) );
+ orderLine.setOlQty( OL_QTY );
+ orderLine.setOlDiscount( OL_DISCOUNT );
+ orderLine.setOlComment( OL_COMMENTS );
+ orderLine.setOrders( order );
+
+ orderLineDao.shrani( orderLine );
+ order.getOrderLines().add( orderLine );
+
+ }
+
+ CX_TYPE = credit_cards[getRandomInt( 0, num_card_types - 1 )];
+ CX_NUM = getRandomNString( 16 );
+ CX_NAME = getRandomAString( 14, 30 );
+ cal = new GregorianCalendar();
+ cal.add( Calendar.DAY_OF_YEAR, getRandomInt( 10, 730 ) );
+ CX_EXPIRY = new java.sql.Date( cal.getTime().getTime() );
+ CX_AUTH_ID = getRandomInt( 1, NUM_AUTHORS );
+ CX_CO_ID = getRandomInt( 1, 92 );
+
+ CcXacts ccXacts = new CcXacts();
+
+ ccXacts.setCountry( countryDao.findById( CX_CO_ID ) );
+ ccXacts.setOrders( order );
+ ccXacts.setCxType( CX_TYPE );
+ ccXacts.setCxNum( CX_NUM );
+ ccXacts.setCxName( CX_NAME );
+ ccXacts.setCxExpiry( CX_EXPIRY );
+ ccXacts.setCxAuthId( authorDao.findById( CX_AUTH_ID ));
+ ccXacts.setCxXactAmt( O_TOTAL );
+ ccXacts.setCxXactDate( O_SHIP_DATE );
+
+ ccXacts.setOrders( order );
+
+ ccXacts.setCountry( countryDao.findById( CX_CO_ID ) );
+
+ order.getCcXactses().add( ccXacts );
+
+ ccXactsDao.shrani( ccXacts );
+
+ }
+
+ System.out.println( "" );
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/GenerateMongo.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/GenerateMongo.java
new file mode 100644
index 0000000..e882b38
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/GenerateMongo.java
@@ -0,0 +1,175 @@
+package eu.cloudscale.showcase.generate;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import org.omg.CosNaming._BindingIteratorImplBase;
+
+import eu.cloudscale.showcase.db.dao.IAddressDao;
+import eu.cloudscale.showcase.db.dao.IAuthorDao;
+import eu.cloudscale.showcase.db.dao.ICcXactsDao;
+import eu.cloudscale.showcase.db.dao.ICountryDao;
+import eu.cloudscale.showcase.db.dao.ICustomerDao;
+import eu.cloudscale.showcase.db.dao.IItemDao;
+import eu.cloudscale.showcase.db.dao.IOrderLineDao;
+import eu.cloudscale.showcase.db.dao.IOrdersDao;
+import eu.cloudscale.showcase.db.model.ICcXacts;
+import eu.cloudscale.showcase.db.model.IItem;
+import eu.cloudscale.showcase.db.model.IOrderLine;
+import eu.cloudscale.showcase.db.model.IOrders;
+import eu.cloudscale.showcase.db.model.mongo.Item;
+
+public class GenerateMongo extends AGenerate
+{
+
+ public GenerateMongo()
+ {
+ super();
+ }
+
+ @Override
+ public void populateOrdersAndCC_XACTSTable()
+ {
+ GregorianCalendar cal;
+ String[] credit_cards = {"VISA", "MASTERCARD", "DISCOVER", "AMEX",
+ "DINERS" };
+ int num_card_types = 5;
+ String[] ship_types = {"AIR", "UPS", "FEDEX", "SHIP", "COURIER", "MAIL" };
+ int num_ship_types = 6;
+
+ String[] status_types = {"PROCESSING", "SHIPPED", "PENDING", "DENIED" };
+ int num_status_types = 4;
+
+ // Order variables
+ int O_C_ID;
+ java.sql.Timestamp O_DATE;
+ double O_SUB_TOTAL;
+ double O_TAX;
+ double O_TOTAL;
+ String O_SHIP_TYPE;
+ java.sql.Timestamp O_SHIP_DATE;
+ int O_BILL_ADDR_ID, O_SHIP_ADDR_ID;
+ String O_STATUS;
+
+ String CX_TYPE;
+ int CX_NUM;
+ String CX_NAME;
+ java.sql.Date CX_EXPIRY;
+ Integer CX_AUTH_ID;
+ int CX_CO_ID;
+
+ System.out.println( "Populating ORDERS, ORDER_LINES, CC_XACTS with "
+ + NUM_ORDERS + " orders" );
+
+ System.out.print( "Complete (in 10,000's): " );
+
+ ICustomerDao customerDao = super.db.getCustomerDaoImpl();
+ IAuthorDao authorDao = super.db.getAuthorDaoImpl();
+ IAddressDao addressDao = super.db.getAddressDaoImpl();
+ IItemDao itemDao = super.db.getItemDaoImpl();
+ ICountryDao countryDao = super.db.getCountryDaoImpl();
+ IOrdersDao ordersDao = super.db.getOrdersDaoImpl();
+ IOrderLineDao orderLineDao = super.db.getOrderLineDaoImpl();
+ ICcXactsDao ccXactsDao = super.db.getCcXactsDaoImpl();
+
+ for ( int i = 1; i <= NUM_ORDERS; i++ )
+ {
+ if ( i % 10000 == 0 )
+ System.out.print( i / 10000 + " " );
+
+ int num_items = getRandomInt( 1, 5 );
+ O_C_ID = getRandomInt( 1, NUM_CUSTOMERS );
+ cal = new GregorianCalendar();
+ cal.add( Calendar.DAY_OF_YEAR, -1 * getRandomInt( 1, 60 ) );
+ O_DATE = new java.sql.Timestamp( cal.getTime().getTime() );
+ O_SUB_TOTAL = (double) getRandomInt( 1000, 999999 ) / 100;
+ O_TAX = O_SUB_TOTAL * 0.0825;
+ O_TOTAL = O_SUB_TOTAL + O_TAX + 3.00 + num_items;
+ O_SHIP_TYPE = ship_types[getRandomInt( 0, num_ship_types - 1 )];
+ cal.add( Calendar.DAY_OF_YEAR, getRandomInt( 0, 7 ) );
+ O_SHIP_DATE = new java.sql.Timestamp( cal.getTime().getTime() );
+
+ O_BILL_ADDR_ID = getRandomInt( 1, 2 * NUM_CUSTOMERS );
+ O_SHIP_ADDR_ID = getRandomInt( 1, 2 * NUM_CUSTOMERS );
+ O_STATUS = status_types[getRandomInt( 0, num_status_types - 1 )];
+
+ IOrders order = ordersDao.getObject();
+
+ // Set parameter
+ order.setOId( i );
+ order.setCustomer( customerDao.findById( O_C_ID ) );
+ order.setODate( new Date( O_DATE.getTime() ) );
+ order.setOSubTotal( O_SUB_TOTAL );
+ order.setOTax( O_TAX );
+ order.setOTotal( O_TOTAL );
+ order.setOShipType( O_SHIP_TYPE );
+ order.setOShipDate( O_SHIP_DATE );
+ order.setAddressByOBillAddrId( addressDao.findById( O_BILL_ADDR_ID ) );
+ order.setAddressByOShipAddrId( addressDao.findById( O_SHIP_ADDR_ID ) );
+ order.setOStatus( O_STATUS );
+// order.setCcXactses( new HashSet<ICcXacts>() );
+// order.setOrderLines( new HashSet<IOrderLine>() );
+
+ for ( int j = 1; j <= num_items; j++ )
+ {
+ int OL_ID = j;
+ int OL_O_ID = i;
+ int OL_I_ID = getRandomInt( 1, NUM_ITEMS );
+ int OL_QTY = getRandomInt( 1, 300 );
+ double OL_DISCOUNT = (double) getRandomInt( 0, 30 ) / 100;
+ String OL_COMMENTS = getRandomAString( 20, 100 );
+ IOrderLine orderLine = orderLineDao.getObject();
+ orderLine.setOlId( OL_ID );
+
+ Item item = (Item) itemDao.findById( OL_I_ID );
+ Integer olQty = item.getOlQty();
+ item.setOlQty( (olQty == null ? 0 : olQty) + 1 );
+ itemDao.shrani( item );
+
+ orderLine.setItem( item );
+ orderLine.setOlQty( OL_QTY );
+ orderLine.setOlDiscount( OL_DISCOUNT );
+ orderLine.setOlComment( OL_COMMENTS );
+ orderLine.setOrders( order );
+
+ ordersDao.shrani( order );
+ orderLineDao.shrani( orderLine );
+// order.getOrderLines().add(orderLine);
+ ordersDao.shrani( order );
+ }
+
+ CX_TYPE = credit_cards[getRandomInt( 0, num_card_types - 1 )];
+ CX_NUM = getRandomNString( 16 );
+ CX_NAME = getRandomAString( 14, 30 );
+ cal = new GregorianCalendar();
+ cal.add( Calendar.DAY_OF_YEAR, getRandomInt( 10, 730 ) );
+ CX_EXPIRY = new java.sql.Date( cal.getTime().getTime() );
+ CX_AUTH_ID = getRandomInt( 1, NUM_AUTHORS );
+ CX_CO_ID = getRandomInt( 1, 92 );
+
+ ICcXacts ccXacts = ccXactsDao.getObject();
+ ccXacts.setId( i );
+ ccXacts.setCountry( countryDao.findById( CX_CO_ID ) );
+ ccXacts.setId( order.getOId() );
+ ccXacts.setCxType( CX_TYPE );
+ ccXacts.setCxNum( CX_NUM );
+ ccXacts.setCxName( CX_NAME );
+ ccXacts.setCxExpiry( CX_EXPIRY );
+ ccXacts.setCxAuthId( authorDao.findById( CX_AUTH_ID ) );
+ ccXacts.setCxXactAmt( O_TOTAL );
+ ccXacts.setCxXactDate( O_SHIP_DATE );
+
+ ccXacts.setOrders(order);
+ ccXactsDao.shrani( ccXacts );
+
+// order.getCcXactses().add( ccXacts );
+
+ ordersDao.shrani( order );
+
+ }
+
+ System.out.println( "" );
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/IGenerate.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/IGenerate.java
new file mode 100644
index 0000000..3d2b207
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/generate/IGenerate.java
@@ -0,0 +1,17 @@
+package eu.cloudscale.showcase.generate;
+
+public interface IGenerate
+{
+
+ public void populateCountryTable();
+
+ public void populateAuthorTable();
+
+ public void populateAddressTable();
+
+ public void populateCustomerTable();
+
+ public void populateItemTable();
+
+ public void populateOrdersAndCC_XACTSTable();
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/AController.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/AController.java
new file mode 100644
index 0000000..beb2cee
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/AController.java
@@ -0,0 +1,123 @@
+package eu.cloudscale.showcase.servlets;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Properties;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PropertiesLoaderUtils;
+import org.springframework.ui.Model;
+import org.springframework.util.PropertyPlaceholderHelper;
+
+import eu.cloudscale.showcase.db.IService;
+import eu.cloudscale.showcase.db.dao.IItemDao;
+import eu.cloudscale.showcase.db.model.IItem;
+
+public abstract class AController
+{
+ @Autowired
+ @Qualifier("service")
+ protected IService service;
+
+ public List<IItem> getPromotional()
+ {
+ IItemDao itemDao = service.getItemDaoImpl();
+ List<IItem> promotional = itemDao.getPromotional();
+
+ return promotional;
+ }
+
+ protected String getUrl2(Integer shoppingId, Integer customerId, String url1)
+ {
+ String url = new String(url1);
+ if( shoppingId != null)
+ {
+ url += "?SHOPPING_ID=" + shoppingId;
+ if( customerId != null )
+ {
+ url += "&C_ID=" + customerId;
+ }
+ }
+ else if ( customerId != null )
+ {
+ url += "?C_ID=" + customerId;
+ }
+
+ return url;
+ }
+
+ protected String getUrl1(Integer shoppingId, Integer customerId, String url1)
+ {
+ String url = new String(url1);
+ if( shoppingId != null )
+ {
+ url += "&SHOPPING_ID=" + shoppingId;
+ }
+
+ if( customerId != null )
+ {
+ url += "&C_ID=" + customerId;
+ }
+
+ return url;
+ }
+
+ protected String getShoppingCartUrl(Integer shoppingId, Integer customerId)
+ {
+ return getUrl2( shoppingId, customerId, "/shopping-cart" );
+ }
+
+ protected String getHomeUrl(Integer shoppingId, Integer customerId)
+ {
+ return getUrl2( shoppingId, customerId, "/" );
+ }
+
+ protected String getSearchRequestUrl(Integer shoppingId, Integer customerId)
+ {
+ return getUrl2( shoppingId, customerId, "/search" );
+ }
+
+ protected String getOrderInquiryUrl(Integer shoppingId, Integer customerId)
+ {
+ return getUrl2( shoppingId, customerId, "/order-inquiry" );
+ }
+
+ protected void setupFrontend(Model model, Integer shoppingId, Integer customerId)
+ {
+ String shoppingCartUrl = getShoppingCartUrl( shoppingId, customerId );
+ model.addAttribute( "shoppingCartUrl", shoppingCartUrl );
+
+ String searchUrl = getSearchRequestUrl( shoppingId, customerId );
+ model.addAttribute( "searchUrl", searchUrl );
+
+ String homeUrl = getHomeUrl( shoppingId, customerId );
+ model.addAttribute( "homeUrl", homeUrl );
+
+ String orderInquiryUrl = getOrderInquiryUrl(shoppingId, customerId);
+ model.addAttribute( "orderInquiryUrl", orderInquiryUrl );
+
+ model.addAttribute( "cssResourceUrl", getApplicationProperties().get( "eu.cloudscale.files.url.css" ));
+ model.addAttribute( "imgResourceUrl", getApplicationProperties().get( "eu.cloudscale.files.url.img" ));
+ model.addAttribute( "jsResourceUrl", getApplicationProperties().get( "eu.cloudscale.files.url.js" ));
+ }
+
+ protected Properties getApplicationProperties()
+ {
+ Resource resource = new ClassPathResource("app.properties");
+ Properties props = null;
+ try
+ {
+ props = PropertiesLoaderUtils.loadProperties(resource);
+ }
+ catch ( IOException e )
+ {
+ e.printStackTrace();
+ }
+
+ return props;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/BestSellersController.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/BestSellersController.java
new file mode 100644
index 0000000..9f28d8f
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/BestSellersController.java
@@ -0,0 +1,41 @@
+package eu.cloudscale.showcase.servlets;
+
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@Controller
+@RequestMapping("/best-sellers")
+public class BestSellersController extends AController
+{
+ @RequestMapping(value="", method=RequestMethod.GET)
+ public String bestSellers(@RequestParam( value="SUBJECT", required=false) String category,
+ @RequestParam( value="C_ID", required=false) Integer customerId,
+ @RequestParam( value="SHOPPING_ID", required=false ) Integer shoppingId,
+ HttpServletRequest request, Model model)
+ {
+ HttpSession session = request.getSession(false);
+
+ List<Object[]> res = service.getBestSellers( category );
+ model.addAttribute( "products", res );
+
+ String productUrl = getProductUrl(shoppingId, customerId);
+ model.addAttribute( "productUrl", productUrl);
+ model.addAttribute( "promotional", getPromotional() );
+ setupFrontend( model, shoppingId, customerId );
+
+ return "best-sellers";
+ }
+
+ private String getProductUrl(Integer shoppingId, Integer customerId)
+ {
+ return getUrl2(shoppingId, customerId, "");
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/BuyConfirmController.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/BuyConfirmController.java
new file mode 100644
index 0000000..e25e6e8
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/BuyConfirmController.java
@@ -0,0 +1,143 @@
+package eu.cloudscale.showcase.servlets;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import eu.cloudscale.showcase.db.BuyConfirmResult;
+import eu.cloudscale.showcase.db.dao.ICountryDao;
+import eu.cloudscale.showcase.db.model.ICountry;
+
+@Controller
+@RequestMapping("/buy-confirm")
+public class BuyConfirmController extends AController
+{
+ @RequestMapping(value="", method=RequestMethod.GET)
+ public String get(HttpServletRequest request,
+ Model model)
+ {
+ HttpSession session = request.getSession(false);
+
+ ArrayList<String> errors = new ArrayList<String>();
+
+ String shoppingIdString = request.getParameter( "SHOPPING_ID" );
+ Integer shoppingId = null;
+ if( shoppingIdString != null && !shoppingIdString.isEmpty() )
+ {
+ shoppingId = Integer.parseInt( shoppingIdString );
+ }
+
+ String customerIdString = request.getParameter( "C_ID" );
+ Integer customerId = null;
+ if( customerIdString != null && !customerIdString.isEmpty() )
+ {
+ customerId = Integer.parseInt( customerIdString );
+ }
+
+ String ccType = request.getParameter( "CC_TYPE" );
+ String ccNumber_str = request.getParameter( "CC_NUMBER" );
+ Long ccNumber = null;
+ if( !ccNumber_str.isEmpty() )
+ ccNumber = Long.parseLong( ccNumber_str );
+
+ SimpleDateFormat sdf = new SimpleDateFormat("mm/dd/yyyy");
+ String ccName = request.getParameter( "CC_NAME" );
+ Date ccExpiry = null;
+ try
+ {
+ ccExpiry = sdf.parse(request.getParameter( "CC_EXPIRY" ));
+ }
+ catch ( ParseException e )
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ String shipping = request.getParameter( "SHIPPING" );
+ String street1 = request.getParameter( "street1" );
+
+
+ BuyConfirmResult res = null;
+ if( street1 != null && street1.equals( "" ))
+ {
+ checkEmptiness(errors, shoppingId, customerId, ccType, ccNumber, ccName, ccExpiry, shipping);
+ if( errors.isEmpty() )
+ res = service.doBuyConfirm( shoppingId, customerId, ccType, ccNumber, ccName, ccExpiry, shipping);
+ }
+ else
+ {
+ String street2 = request.getParameter("street2");
+ String city = request.getParameter("city");
+ String state = request.getParameter( "state" );
+ String zip = request.getParameter("zip");
+ String country = request.getParameter("country");
+ checkEmptiness(errors, shoppingId, customerId, ccType, ccNumber, ccName, ccExpiry, shipping, street1, country, city, state, zip);
+ if( errors.isEmpty() )
+ res = service.doBuyConfirm(shoppingId, customerId, ccType, ccNumber, ccName, ccExpiry, shipping, street1, street2, city, state, zip, country);
+ }
+
+ model.addAttribute("errors", errors);
+ model.addAttribute("results", res);
+ setupFrontend( model, shoppingId, customerId );
+ return "buy-confirm";
+ }
+
+ private void checkEmptiness(ArrayList<String> errors, Integer shoppingId,
+ Integer customerId, String ccType, Long ccNumber, String ccName,
+ Date ccExpiry, String shipping)
+ {
+ if(shoppingId == null)
+ errors.add( "Shipping id is null!" );
+ if( customerId == null)
+ errors.add( "Customer id is null" );
+ if( ccType == null || ccType.isEmpty() )
+ errors.add( "ccType is null" );
+ if( ccNumber == null)
+ errors.add("ccNumber is null");
+ if( ccName == null || ccName.isEmpty() )
+ errors.add( "ccName is null" );
+ if( ccExpiry == null)
+ errors.add( "ccExpiry is null" );
+ if( shipping == null || shipping.isEmpty() )
+ errors.add( "Shipping is null" );
+ }
+
+ private boolean countryExist( String country)
+ {
+ ICountryDao countryDao = service.getCountryDaoImpl();
+
+ ICountry country1 = countryDao.getByName( country );
+ return country1 == null;
+ }
+
+ private void checkEmptiness(ArrayList<String> errors, Integer shoppingId,
+ Integer customerId, String ccType, Long ccNumber, String ccName,
+ Date ccExpiry, String shipping, String street, String country, String city, String state, String zip)
+ {
+ checkEmptiness( errors, shoppingId, customerId, ccType, ccNumber, ccName, ccExpiry, shipping );
+
+ if( city == null )
+ errors.add( "City is null" );
+
+ if( state == null )
+ errors.add( "State is null" );
+
+ if( zip == null )
+ errors.add( "Zip is null" );
+
+ if( street == null )
+ errors.add( "Street1 or street2 is null" );
+
+ if( !countryExist(country) )
+ errors.add( "That country doesn't exist!" );
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/BuyController.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/BuyController.java
new file mode 100644
index 0000000..0f38231
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/BuyController.java
@@ -0,0 +1,227 @@
+package eu.cloudscale.showcase.servlets;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import eu.cloudscale.showcase.db.dao.IAddressDao;
+import eu.cloudscale.showcase.db.dao.ICountryDao;
+import eu.cloudscale.showcase.db.dao.ICustomerDao;
+import eu.cloudscale.showcase.db.dao.IShoppingCartDao;
+import eu.cloudscale.showcase.db.model.IAddress;
+import eu.cloudscale.showcase.db.model.ICountry;
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.model.IShoppingCart;
+import eu.cloudscale.showcase.db.model.IShoppingCartLine;
+
+@Controller
+@RequestMapping( "/buy" )
+public class BuyController extends AController
+{
+
+ @RequestMapping( value = "", method = RequestMethod.GET )
+ @Transactional
+ public String get(
+ @RequestParam( value = "SHOPPING_ID", required = false ) Integer shoppingId,
+ @RequestParam( value = "C_ID", required = false ) Integer customerId,
+ @RequestParam( value = "RETURNING_FLAG", required = false ) String returningFlag,
+ HttpServletRequest request, Model model)
+ {
+ HttpSession session = request.getSession(false);
+
+
+
+ ArrayList<String> errors = new ArrayList<String>();
+
+ ICustomerDao customerDao = service.getCustomerDaoImpl();
+ ICountryDao countryDao = service.getCountryDaoImpl();
+ IShoppingCartDao scDao = service.getShoppingCartDaoImpl();
+ IAddressDao addrDao = service.getAddressDaoImpl();
+
+ ICustomer customer = null;
+ if ( returningFlag.equals( "Y" ) )
+ {
+ String uname = request.getParameter( "username" );
+ String passwd = request.getParameter( "password" );
+
+ if ( uname.length() == 0 || passwd.length() == 0 )
+ {
+ errors.add( "Username and password cannot be empty!" );
+ }
+ else
+ {
+ customer = customerDao.getUserBy( uname, passwd );
+ if ( customer == null )
+ {
+ errors.add( "Invalid username or password!" );
+ }
+
+// if ( errors.isEmpty() )
+// {
+// session.setAttribute( "customer", customer );
+// }
+ }
+ }
+ else if ( returningFlag.equals( "N" ) )
+ {
+ String fname = request.getParameter( "fname" );
+ checkEmptiness( fname, "First name", errors );
+ String lname = request.getParameter( "lname" );
+ checkEmptiness( lname, "Last name", errors );
+ String city = request.getParameter( "city" );
+ String state = request.getParameter( "state" );
+ String street1 = request.getParameter( "street1" );
+ String street2 = request.getParameter( "street2" );
+ String zip = request.getParameter( "zip" );
+ String country = request.getParameter( "country" );
+ checkEmptiness( country, "Country", errors );
+ String phone = request.getParameter( "phone" );
+ String email = request.getParameter( "email" );
+ String birthdate = request.getParameter( "birthdate" );
+ String data = request.getParameter( "data" );
+
+ if ( errors.isEmpty() )
+ {
+ customer = customerDao.getObject();
+ customer.setCFname( fname );
+ customer.setCLname( lname );
+
+ IAddress address = addrDao.getObject();
+ address.setAddrCity( city );
+ address.setAddrState( state );
+ address.setAddrStreet1( street1 );
+ address.setAddrStreet2( street2 );
+ address.setAddrZip( zip );
+
+
+
+ ICountry countryObj = countryDao.getByName( country );
+ if ( countryObj == null )
+ {
+ errors.add( "Country " + country + " doesn't exist" );
+ }
+ else
+ {
+ address.setCountry( countryObj );
+ }
+
+ address.getCustomers().add( customer );
+ addrDao.shrani( address );
+
+ customer.setAddress( address );
+ customer.setCPhone( phone );
+ SimpleDateFormat sdf = new SimpleDateFormat( "dd/mm/yyyy" );
+
+ try
+ {
+ customer.setCBirthdate( sdf.parse( birthdate ) );
+ }
+ catch ( ParseException e )
+ {
+ e.printStackTrace();
+ }
+ customer.setCData( data );
+ customer.setCEmail( email );
+ customer.setCBalance( 0.0 );
+ customer.setCDiscount( (int) ( java.lang.Math.random() * 51 ) );
+ customer.setCExpiration( new Date(
+ System.currentTimeMillis() + 7200000 ) );
+ customer.setCLastVisit( new Date( System.currentTimeMillis() ) );
+ customer.setCLogin( new Date( System.currentTimeMillis() ) );
+ customer.setCSince( new Date( System.currentTimeMillis() ) );
+ customer.setCYtdPmt( 0.0 );
+ customer.setCUname( "" );
+ customer.setCPasswd( "" );
+ customerDao.shrani( customer );
+ customer.setCUname( DigSyl( customer.getCId(), 0 ).toLowerCase() );
+ customer.setCPasswd( customer.getCUname().toLowerCase() );
+ customerDao.shrani( customer ); // update it with username and
+ // password
+ }
+ }
+ else
+ {
+ errors.add( "RETURNING_FLAG not set to Y or N!" );
+ }
+
+ if ( shoppingId == null )
+ {
+ errors.add( "Shopping cart ID not set!" );
+ }
+
+ IShoppingCart cart = scDao.findById( shoppingId );
+ model.addAttribute( "errors", errors );
+ model.addAttribute( "cart", cart );
+ model.addAttribute( "customer", customer );
+
+// if( cart != null )
+// model.addAttribute( "subTotal", getSubTotal( cart.getShoppingCartLines() ) );
+
+ setupFrontend(model, shoppingId, customerId);
+ return "buy";
+ }
+
+ private double getSubTotal(Set<IShoppingCartLine> shoppingCartLines)
+ {
+ double total = 0;
+ for ( IShoppingCartLine scl : shoppingCartLines )
+ {
+ total += scl.getItem().getICost();
+ }
+
+ return total;
+ }
+
+ private void checkEmptiness(String obj, String desc,
+ ArrayList<String> errors)
+ {
+ if ( obj == null || obj.isEmpty() )
+ {
+ errors.add( desc + " is empty!" );
+ }
+ }
+
+ private static final String[] digS = {"BA", "OG", "AL", "RI", "RE", "SE",
+ "AT", "UL", "IN", "NG" };
+
+ public String DigSyl(int d, int n)
+ {
+ String s = "";
+
+ if ( n == 0 )
+ return ( DigSyl( d ) );
+ for ( ; n > 0; n-- )
+ {
+ int c = d % 10;
+ s = digS[c] + s;
+ d = d / 10;
+ }
+
+ return ( s );
+ }
+
+ private String DigSyl(int d)
+ {
+ String s = "";
+
+ for ( ; d != 0; d = d / 10 )
+ {
+ int c = d % 10;
+ s = digS[c] + s;
+ }
+
+ return ( s );
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/CustomerRegistrationController.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/CustomerRegistrationController.java
new file mode 100644
index 0000000..c3a9dd8
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/CustomerRegistrationController.java
@@ -0,0 +1,53 @@
+package eu.cloudscale.showcase.servlets;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import eu.cloudscale.showcase.db.model.ICustomer;
+
+
+@Controller
+@RequestMapping( "/customer-registration" )
+public class CustomerRegistrationController extends AController
+{
+
+ @RequestMapping( "" )
+ public String get(
+ @RequestParam( value = "C_ID", required = false ) Integer customerId,
+ @RequestParam( value = "SHOPPING_ID", required = false ) Integer shoppingId,
+ HttpServletRequest request, Model model)
+ {
+ HttpSession session = request.getSession( false );
+
+ if ( session == null )
+ session = request.getSession( true );
+
+ ICustomer customer = null;
+ if ( customerId != null )
+ {
+ customer = service.getCustomerDaoImpl().findById( customerId );
+ }
+
+ model.addAttribute( "shoppingId", shoppingId );
+ model.addAttribute( "customerId", customerId );
+
+ String shoppingCartUrl = getShoppingCartUrl( shoppingId, customerId );
+ model.addAttribute( "shoppingCartUrl", shoppingCartUrl );
+
+ String searchUrl = getSearchRequestUrl( shoppingId, customerId );
+ model.addAttribute( "searchUrl", searchUrl );
+
+ String homeUrl = getHomeUrl( shoppingId, customerId );
+ model.addAttribute( "homeUrl", homeUrl );
+
+ model.addAttribute( "sessionId", session.getId() );
+
+ setupFrontend( model, shoppingId, customerId );
+ return "customer-registration";
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/HomeController.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/HomeController.java
new file mode 100644
index 0000000..f4225e1
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/HomeController.java
@@ -0,0 +1,102 @@
+package eu.cloudscale.showcase.servlets;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import eu.cloudscale.showcase.db.model.ICustomer;
+
+@Controller
+@RequestMapping( "/" )
+public class HomeController extends AController
+{
+
+ private String[] categories = {"ARTS", "NON-FICTION",
+ "BIOGRAPHIES", "PARENTING", "BUSINESS", "POLITICS", "CHILDREN",
+ "REFERENCE", "COMPUTERS", "RELIGION", "COOKING", "ROMANCE",
+ "HEALTH", "SELF-HELP", "HISTORY", "SCIENCE-NATURE", "HOME",
+ "SCIENCE-FICTION", "HUMOR", "SPORTS", "LITERATURE", "MYSTERY" };
+
+
+ private class Split
+ {
+
+ public String left, right, leftUrl, rightUrl;
+
+ public Split(String l, String lUrl, String r, String rUrl)
+ {
+ left = l;
+ leftUrl = lUrl;
+ rightUrl = rUrl;
+ right = r;
+ }
+ }
+
+ /**
+ * Simply selects the home view to render by returning its name.
+ */
+ @RequestMapping( value = "/", method = RequestMethod.GET )
+ public String home(
+ @RequestParam( value = "SHOPPING_ID", required = false ) Integer shoppingId,
+ @RequestParam( value = "C_ID", required = false ) Integer customerId,
+ Locale locale, HttpServletRequest request, Model model)
+ {
+ HttpSession session = request.getSession( false );
+
+ if ( session == null )
+ session = request.getSession( true );
+
+ String categoryUrl = getUrl1( shoppingId, customerId, "" );
+
+ model.addAttribute( "promotional", getPromotional() );
+ model.addAttribute( "categories", prepareCategories( categoryUrl ) );
+
+ model.addAttribute( "categoryUrl", categoryUrl );
+
+ setupFrontend( model, shoppingId, customerId );
+
+ String productUrl = getProductUrl( shoppingId, customerId );
+ model.addAttribute( "productUrl", productUrl );
+
+ return "home";
+ }
+
+
+ private String getProductUrl(Integer shoppingId, Integer customerId)
+ {
+ return getUrl1( shoppingId, customerId, "" );
+ }
+
+ // private String getCategoryUrl(Integer shoppingId, Integer customerId)
+ // {
+ // String url = "";
+ // if( shoppingId != null)
+ // url+="&SHOPPING_ID=" + shoppingId;
+ //
+ // if( customerId != null )
+ // url += "&C_ID=" + customerId;
+ //
+ // return url;
+ // }
+
+ private List<Split> prepareCategories(String url)
+ {
+ ArrayList<Split> cats = new ArrayList<Split>();
+
+ for ( int i = 0; i < categories.length; i += 2 )
+ {
+ cats.add( new Split( categories[i], categories[i] + url,
+ categories[i + 1], categories[i + 1] + url ) );
+ }
+ return cats;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/LoginController.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/LoginController.java
new file mode 100644
index 0000000..519fc5c
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/LoginController.java
@@ -0,0 +1,65 @@
+package eu.cloudscale.showcase.servlets;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import eu.cloudscale.showcase.db.dao.ICustomerDao;
+import eu.cloudscale.showcase.db.model.ICustomer;
+
+@Controller
+@RequestMapping("/login")
+public class LoginController extends AController
+{
+
+ @RequestMapping(value="", method=RequestMethod.GET)
+ public String get(HttpServletRequest request, HttpSession session, Model model)
+ {
+ String referer = request.getParameter("next");
+ if( referer.isEmpty() )
+ referer = request.getHeader( "referer" );
+
+ if( session.getAttribute( "customer" ) != null)
+ return "redirect:" + referer == null ? "/" : referer;
+
+ model.addAttribute("referer", referer);
+ return "login";
+ }
+
+ @RequestMapping(value="", method=RequestMethod.POST)
+ public String post(@RequestParam("username") String username,
+ @RequestParam("password") String password,
+ @RequestParam("referer") String referer,
+ HttpSession session, Model model)
+ {
+ ICustomerDao customerDao = service.getCustomerDaoImpl();
+ ICustomer customer = null;
+
+ if( (customer = customerDao.getUserBy(username, password)) != null )
+ {
+ Date currDate = new Date();
+
+
+ Calendar c = Calendar.getInstance();
+ c.setTime( currDate );
+ c.add( Calendar.HOUR, -1 );
+
+ customer.setCLogin( currDate );
+ customer.setCExpiration( c.getTime() );
+ customerDao.shrani(customer);
+ session.setAttribute( "customer", customer );
+ return "redirect:" + referer;
+ }
+
+ model.addAttribute("errors", "Login failed. Check username and password");
+ return "login";
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/NewProductsController.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/NewProductsController.java
new file mode 100644
index 0000000..b3d48d4
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/NewProductsController.java
@@ -0,0 +1,76 @@
+package eu.cloudscale.showcase.servlets;
+
+import java.util.Locale;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@Controller
+@RequestMapping( "/new-products" )
+public class NewProductsController extends AController
+{
+
+// @RequestMapping( value = "/", method = RequestMethod.GET )
+// public String newProducts(Locale locale, Model model)
+// {
+// return "new-products";
+// }
+
+ @RequestMapping( value = "", method = RequestMethod.GET )
+ public String newProductsCategory(
+ @RequestParam( value="SUBJECT", required=false) String category,
+ @RequestParam( value="C_ID", required=false) Integer customerId,
+ @RequestParam( value="SHOPPING_ID", required=false ) Integer shoppingId,
+ Locale locale,
+ HttpServletRequest request,
+ Model model)
+ {
+ HttpSession session = request.getSession(false);
+
+ return getNewProducts(category, model, customerId, shoppingId );
+ }
+
+// @RequestMapping( value = "/", method = RequestMethod.GET )
+// public String newProducts(@PathVariable("category") String category,
+// @PathVariable("customerId") Integer customerId,
+// Model model)
+// {
+//
+// return getNewProducts( category, model, customerId, null);
+// }
+//
+// @RequestMapping( value = "/{category}/{customerId}/{shoppingId}", method = RequestMethod.GET )
+// public String newProducts(@PathVariable("category") String category,
+// @PathVariable("customerId") Integer customerId,
+// @PathVariable("shoppingId") Integer shoppingId,
+// Model model)
+// {
+//
+// return getNewProducts( category, model, customerId, shoppingId);
+// }
+
+ private String getNewProducts(String category, Model model, Integer customerId, Integer shoppingId)
+ {
+
+ String productUrl = getProductUrl(shoppingId, customerId);
+ model.addAttribute( "productUrl", productUrl);
+
+ model.addAttribute( "products", service.getNewProducts( category ) );
+ model.addAttribute( "promotional", getPromotional() );
+
+ setupFrontend(model, shoppingId, customerId);
+ return "new-products";
+ }
+
+ private String getProductUrl(Integer shoppingId, Integer customerId)
+ {
+ return getUrl1(shoppingId, customerId, "");
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/OrderDisplayController.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/OrderDisplayController.java
new file mode 100644
index 0000000..98a2933
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/OrderDisplayController.java
@@ -0,0 +1,92 @@
+package eu.cloudscale.showcase.servlets;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import eu.cloudscale.showcase.db.model.ICustomer;
+import eu.cloudscale.showcase.db.model.IOrderLine;
+import eu.cloudscale.showcase.db.model.IOrders;
+
+@Controller
+@RequestMapping("/order-display")
+public class OrderDisplayController extends AController
+{
+ @SuppressWarnings( {"unchecked", "rawtypes" } )
+ @RequestMapping(method=RequestMethod.GET)
+ public String get(HttpServletRequest request, Model model)
+ {
+ HttpSession session = request.getSession(false);
+
+ if( session == null )
+ session = request.getSession(true);
+
+ Integer customerId = null;
+ try
+ {
+ customerId = Integer.parseInt( request.getParameter("C_ID") );
+ }
+ catch(Exception e) {}
+
+ Integer shoppingId = null;
+ try
+ {
+ shoppingId = Integer.parseInt( request.getParameter("SHOPPING_ID") );
+ }
+ catch(Exception e) {}
+
+ String uname = request.getParameter("username");
+ String passwd = request.getParameter("password");
+
+ ArrayList<String> errors = new ArrayList<String>();
+
+ IOrders order = null;
+ List<IOrderLine> orderLines = null;
+
+ if (uname != null && passwd != null)
+ {
+
+ ICustomer customer = service.getCustomerDaoImpl().getUserBy( uname, passwd);
+
+ if (customer == null)
+ {
+ errors.add( "Error: Incorrect password or username.\n" );
+ }
+ else
+ {
+ order = service.getOrdersDaoImpl().getMostRecentOrder( customer );
+ if (order == null)
+ {
+ errors.add("User doesn't have orders");
+ }
+ else
+ {
+ orderLines = service.getOrderLineDaoImpl().findAllByOrder( order );
+ }
+ }
+
+ }
+ else
+ {
+ errors.add("Error: TPCW_order_display_servlet, uname and passwd not set!.\n");
+ }
+
+ if( errors.isEmpty() )
+ {
+ model.addAttribute( "order", order );
+ model.addAttribute( "orderLines", orderLines );
+ }
+
+ model.addAttribute( "errors", errors);
+
+ setupFrontend( model, shoppingId, customerId );
+ return "order-display";
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/OrderInquiryController.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/OrderInquiryController.java
new file mode 100644
index 0000000..167c360
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/OrderInquiryController.java
@@ -0,0 +1,56 @@
+package eu.cloudscale.showcase.servlets;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+@Controller
+@RequestMapping( "/order-inquiry" )
+public class OrderInquiryController extends AController
+{
+
+ @RequestMapping( method = RequestMethod.GET )
+ public String get(HttpServletRequest request, Model model)
+ {
+ HttpSession session = request.getSession( false );
+
+ if ( session == null )
+ session = request.getSession( true );
+
+ Integer C_ID = null;
+ try
+ {
+ C_ID = Integer.parseInt(request.getParameter( "C_ID" ));
+ }
+ catch(Exception e)
+ {
+ }
+
+ Integer SHOPPING_ID = null;
+ try
+ {
+ SHOPPING_ID = Integer.parseInt(request.getParameter( "SHOPPING_ID" ));
+ }
+ catch(Exception e)
+ {
+ }
+
+ if ( C_ID != null )
+ {
+ model.addAttribute( "customerId", C_ID );
+ }
+
+ if ( SHOPPING_ID != null )
+ {
+ model.addAttribute( "shoppingId", SHOPPING_ID );
+ }
+
+ setupFrontend( model, SHOPPING_ID, C_ID );
+ return "order-inquiry";
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/ProductDetailServlet.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/ProductDetailServlet.java
new file mode 100644
index 0000000..546ee21
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/ProductDetailServlet.java
@@ -0,0 +1,67 @@
+package eu.cloudscale.showcase.servlets;
+
+import java.util.Locale;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import eu.cloudscale.showcase.db.dao.IItemDao;
+import eu.cloudscale.showcase.db.model.IItem;
+
+@Controller
+@RequestMapping("/product-detail")
+public class ProductDetailServlet extends AController
+{
+ private @Autowired HttpServletRequest request;
+
+ @RequestMapping(method = RequestMethod.GET)
+ public String get(
+ @RequestParam(value= "I_ID", required=false) Integer itemId,
+ @RequestParam(value = "C_ID", required=false ) Integer customerId,
+ @RequestParam(value = "SHOPPING_ID", required=false) Integer shoppingId,
+ HttpServletRequest request,
+ Locale locale,
+ Model model)
+ {
+ HttpSession session = request.getSession(false);
+
+ IItemDao itemDao = service.getItemDaoImpl();
+ IItem item = itemDao.findById(itemId);
+
+ String addToShoppingCartUrl = buildAddToShoppingCartUrl(shoppingId, customerId, itemId);
+ model.addAttribute( "addToShoppingCartUrl", addToShoppingCartUrl);
+
+ String adminUrl = buildAdminUrl(shoppingId, customerId, itemId);
+ model.addAttribute( "adminUrl", adminUrl );
+
+ model.addAttribute( "item", item);
+ setupFrontend( model, shoppingId, customerId );
+
+ return "product_detail";
+ }
+
+ private String buildAddToShoppingCartUrl(Integer shoppingId, Integer customerId, Integer itemId)
+ {
+ String url = getUrl2(shoppingId, customerId, "/shopping-cart");
+ if( url.equals( "/shopping-cart" ))
+ url += "?";
+
+ url += "&I_ID=" + itemId + "&QTY=1&ADD_FLAG=Y";
+ return url;
+ }
+
+ private String buildAdminUrl(Integer shoppingId, Integer customerId, int id)
+ {
+ return getUrl2(shoppingId, customerId, "/admin");
+ }
+
+
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/SearchController.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/SearchController.java
new file mode 100644
index 0000000..6234843
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/SearchController.java
@@ -0,0 +1,83 @@
+package eu.cloudscale.showcase.servlets;
+
+import java.util.ArrayList;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import eu.cloudscale.showcase.db.common.DatabaseHelper;
+
+@Controller
+@RequestMapping("/search")
+public class SearchController extends AController
+{
+
+ @RequestMapping( method=RequestMethod.GET )
+ public String get(HttpServletRequest request, Model model)
+ {
+
+ HttpSession session = request.getSession(false);
+
+ String field = request.getParameter("searchField");
+ String keyword = request.getParameter( "keyword" );
+ ArrayList<String> errors = new ArrayList<String>();
+
+ if( keyword == null)
+ {
+ keyword = "";
+ errors.add( "Search string is empty" );
+ model.addAttribute( "errors", errors );
+ }
+
+ if( errors.isEmpty() )
+ {
+ if( field.equalsIgnoreCase( "author" ))
+ {
+ model.addAttribute( "results", service.searchByAuthor(keyword) );
+ }
+ else if( field.equalsIgnoreCase( "title" ))
+ {
+ model.addAttribute( "results", service.searchByTitle(keyword) );
+ }
+ else if( field.equalsIgnoreCase( "subject" ))
+ {
+ model.addAttribute( "results", service.searchBySubject(keyword) );
+ }
+ }
+
+ model.addAttribute( "searchField", field );
+ model.addAttribute( "keyword", keyword );
+ setupUrls( model, request);
+ return "search";
+ }
+
+ private void setupUrls(Model model, HttpServletRequest request)
+ {
+ Integer shoppingId = null;
+ if( request.getParameter( "SHOPPING_ID" ) != null)
+ {
+ shoppingId = Integer.valueOf(request.getParameter( "SHOPPING_ID" ));
+ }
+
+ Integer customerId = null;
+ if( request.getParameter( "C_ID" ) != null)
+ {
+ shoppingId = Integer.valueOf(request.getParameter( "C_ID" ));
+ }
+ setupFrontend( model, shoppingId, customerId);
+
+ String productUrl = getProductUrl(shoppingId, customerId);
+ model.addAttribute( "productUrl", productUrl);
+ }
+
+
+ private String getProductUrl(Integer shoppingId, Integer customerId)
+ {
+ return getUrl2(shoppingId, customerId, "");
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/ShoppingCartController.java b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/ShoppingCartController.java
new file mode 100644
index 0000000..e0208f1
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/java/eu/cloudscale/showcase/servlets/ShoppingCartController.java
@@ -0,0 +1,114 @@
+package eu.cloudscale.showcase.servlets;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import eu.cloudscale.showcase.db.dao.IShoppingCartDao;
+import eu.cloudscale.showcase.db.model.IShoppingCart;
+import eu.cloudscale.showcase.db.model.IShoppingCartLine;
+
+@Controller
+@RequestMapping("/shopping-cart")
+public class ShoppingCartController extends AController
+{
+
+ @RequestMapping(value="", method=RequestMethod.GET)
+ public String get(HttpServletRequest request, Model model)
+ {
+ HttpSession session = request.getSession(false);
+
+ IShoppingCartDao scDao = service.getShoppingCartDaoImpl();
+
+ ArrayList<String> errors = new ArrayList<String>();
+ Integer itemId = null;
+ Integer customerId = null;
+ Integer shoppingId = null;
+ if( request.getParameter( "I_ID" ) != null )
+ {
+ itemId = Integer.parseInt(request.getParameter( "I_ID" ));
+ }
+
+ if( request.getParameter( "C_ID" ) != null )
+ {
+ customerId = Integer.parseInt(request.getParameter( "C_ID" ));
+ }
+
+ if( request.getParameter( "SHOPPING_ID" ) != null )
+ {
+ shoppingId = Integer.parseInt(request.getParameter( "SHOPPING_ID" ));
+ }
+
+ String addFlag = request.getParameter("ADD_FLAG");
+
+ if( shoppingId == null || scDao.findById( shoppingId ) == null )
+ {
+ shoppingId = scDao.createEmptyCart();
+ }
+
+ if( addFlag != null && addFlag.equals( "Y" ) )
+ {
+ if(itemId == null)
+ errors.add("No item id!");
+ }
+
+ if( errors.isEmpty() )
+ {
+ List<Integer> quantities = new ArrayList<Integer>();
+ List<Integer> ids = new ArrayList<Integer>();
+ int i = 0;
+ String curr_QTYstr = request.getParameter( "QTY_" + i ) ;
+ String curr_I_IDstr = request.getParameter( "I_ID_" + i );
+
+ while (curr_I_IDstr != null)
+ {
+ ids.add(Integer.parseInt(curr_I_IDstr));
+ quantities.add(Integer.parseInt((curr_QTYstr)));
+ i++;
+ curr_QTYstr = request.getParameter("QTY_" + i);
+ curr_I_IDstr = request.getParameter("I_ID_" + i);
+ }
+
+ IShoppingCart cart = service.doCart(shoppingId, itemId, ids, quantities);
+ model.addAttribute( "cart", cart);
+// model.addAttribute( "subTotal", getSubTotal(cart.getShoppingCartLines()));
+
+ String customerRegistration = getCustomerRegistrationURL(customerId, shoppingId);
+ model.addAttribute( "checkoutUrl", customerRegistration);
+
+ if( customerId != null )
+ model.addAttribute("customerId", customerId);
+ }
+
+ model.addAttribute("errors", errors);
+ setupFrontend(model, shoppingId, customerId);
+ return "shopping-cart";
+ }
+
+ private double getSubTotal(Set<IShoppingCartLine> shoppingCartLines)
+ {
+ double subtotal = 0;
+ for(IShoppingCartLine scl : shoppingCartLines)
+ {
+ subtotal += scl.getItem().getICost();
+ }
+
+ return subtotal;
+ }
+
+
+ private String getCustomerRegistrationURL(Integer customerId, Integer shoppingId)
+ {
+ return getUrl2(shoppingId, customerId, "/customer-registration");
+ }
+
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/app.properties b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/app.properties
new file mode 100644
index 0000000..38fd22b
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/app.properties
@@ -0,0 +1,3 @@
+eu.cloudscale.files.url.css=https\://s3-eu-west-1.amazonaws.com/showcase-1-a-images/css
+eu.cloudscale.files.url.img=https\://s3-eu-west-1.amazonaws.com/showcase-1-a-images/img
+eu.cloudscale.files.url.js=https\://s3-eu-west-1.amazonaws.com/showcase-1-a-images/js
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/app-context.xml b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/app-context.xml
new file mode 100644
index 0000000..8ce75c3
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/app-context.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+ <!-- These variables are replaced with ones defined in pom.xml -->
+ <import resource="classpath:cache.xml" />
+ <import resource="classpath:${eu.cloudscale.datasource}.xml" />
+</beans>
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/cache.xml b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/cache.xml
new file mode 100644
index 0000000..1709a98
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/cache.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:cache="http://www.springframework.org/schema/cache"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/cache
+ http://www.springframework.org/schema/cache/spring-cache.xsd">
+
+ <cache:annotation-driven />
+
+ <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"
+ p:cache-manager-ref="ehcache" />
+ <bean id="ehcache"
+ class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
+ p:cacheManagerName="myCacheManager" p:shared="true" p:config-location="classpath:ehcache.xml" />
+
+</beans>
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/database/database.aws.hibernate.properties b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/database/database.aws.hibernate.properties
new file mode 100644
index 0000000..81be84a
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/database/database.aws.hibernate.properties
@@ -0,0 +1,6 @@
+jdbc.dbtype=mysql
+jdbc.driverClassName=com.mysql.jdbc.Driver
+jdbc.url=jdbc:mysql://master/databasename
+jdbc.username=<user>
+jdbc.password=<pass>
+jdbc.hibernate.dialect=org.hibernate.dialect.MySQLDialect
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/database/database.aws.mongodb.properties b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/database/database.aws.mongodb.properties
new file mode 100644
index 0000000..b3d04a5
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/database/database.aws.mongodb.properties
@@ -0,0 +1,6 @@
+jdbc.dbtype=mongodb
+mongodb.dbname=tpcw
+mongodb.host=ip
+mongodb.port=27017
+mongodb.username=<user>
+mongodb.password=<pass>
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/ehcache.xml b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/ehcache.xml
new file mode 100644
index 0000000..58ecc72
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/ehcache.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
+ <diskStore path="java.io.tmpdir/Cloudscale-cache"/>
+ <defaultCache
+ eternal="false"
+ maxElementsInMemory="100000"
+ overflowToDisk="false"
+ diskPersistent="false"
+ timeToIdleSeconds="0"
+ timeToLiveSeconds="600"
+ memoryStoreEvictionPolicy="LRU"
+ />
+
+ <cache
+ name="bestSellers"
+ maxElementsInMemory="10000"
+ eternal="false"
+ timeToIdleSeconds="0"
+ timeToLiveSeconds="86400"
+ overflowToDisk="false"/>
+
+ <cache
+ name="newProducts"
+ maxElementsInMemory="10000"
+ eternal="false"
+ timeToIdleSeconds="0"
+ timeToLiveSeconds="86400"
+ overflowToDisk="false"/>
+
+ <cache
+ name="search"
+ maxElementsInMemory="10000"
+ eternal="false"
+ timeToIdleSeconds="0"
+ timeToLiveSeconds="86400"
+ overflowToDisk="false"/>
+
+ <cache
+ name="org.hibernate.cache.spi.UpdateTimestampsCache"
+ maxElementsInMemory="5000"
+ eternal="false"
+ timeToIdleSeconds="0"
+ timeToLiveSeconds="86400"
+ overflowToDisk="false"/>
+
+ <cache
+ name="org.hibernate.cache.internal.StandardQueryCache"
+ maxElementsInMemory="5000"
+ eternal="false"
+ timeToIdleSeconds="0"
+ timeToLiveSeconds="86400"
+ overflowToDisk="false"/>
+</ehcache>
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/generate/database.aws.hibernate.properties b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/generate/database.aws.hibernate.properties
new file mode 100644
index 0000000..ab0a963
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/generate/database.aws.hibernate.properties
@@ -0,0 +1,6 @@
+jdbc.dbtype=mysql
+jdbc.driverClassName=com.mysql.jdbc.Driver
+jdbc.url=jdbc:mysql://master/tpcw
+jdbc.username=<user>
+jdbc.password=<pass>
+jdbc.hibernate.dialect=org.hibernate.dialect.MySQLDialect
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/generate/database.properties b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/generate/database.properties
new file mode 100644
index 0000000..ab0a963
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/generate/database.properties
@@ -0,0 +1,6 @@
+jdbc.dbtype=mysql
+jdbc.driverClassName=com.mysql.jdbc.Driver
+jdbc.url=jdbc:mysql://master/tpcw
+jdbc.username=<user>
+jdbc.password=<pass>
+jdbc.hibernate.dialect=org.hibernate.dialect.MySQLDialect
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/hibernate.xml b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/hibernate.xml
new file mode 100644
index 0000000..19a73c3
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/hibernate.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:tx="http://www.springframework.org/schema/tx"
+ xmlns:jdbc="http://www.springframework.org/schema/jdbc"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:cache="http://www.springframework.org/schema/cache"
+ xsi:schemaLocation="http://www.springframework.org/schema/jdbc
+ http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/tx
+ http://www.springframework.org/schema/tx/spring-tx.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/cache
+ http://www.springframework.org/schema/cache/spring-cache.xsd">
+
+ <context:property-placeholder
+ location="${eu.cloudscale.showcase.generate.properties}" />
+
+ <context:component-scan base-package="eu.cloudscale.showcase.db.dao.hibernate" />
+
+ <bean id="service" class="eu.cloudscale.showcase.db.services.HibernateService" />
+
+ <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
+ destroy-method="close">
+
+ <property name="driverClass" value="${jdbc.driverClassName}" />
+ <property name="jdbcUrl" value="${jdbc.url}" />
+ <property name="user" value="${jdbc.username}" />
+ <property name="password" value="${jdbc.password}" />
+ <!-- these are C3P0 properties -->
+ <property name="acquireIncrement" value="1" />
+ <property name="minPoolSize" value="4" />
+ <property name="maxPoolSize" value="32" />
+ <property name="maxIdleTime" value="60" />
+<!-- <property name="maxConnectionAge" value="180" /> -->
+ <!-- <property name="debugUnreturnedConnectionStackTraces" value="true"
+ /> -->
+ <property name="initialPoolSize" value="4" />
+ <property name="idleConnectionTestPeriod" value="10" />
+ <property name="checkoutTimeout" value="3000" />
+<!-- <property name="maxIdleTimeExcessConnections" value="30" /> -->
+ <property name="unreturnedConnectionTimeout" value="30" />
+ <property name="debugUnreturnedConnectionStackTraces" value="true" />
+ <!-- <property name="automaticTestTable" value="conTest" /> -->
+<!-- <property name="testConnectionOnCheckin" value="true" /> -->
+<!-- <property name="testConnectionOnCheckout" value="true" /> -->
+ </bean>
+
+ <tx:annotation-driven transaction-manager="transactionManager" />
+
+ <bean id="sessionFactory"
+ class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
+ <property name="dataSource" ref="dataSource" />
+
+ <property name="packagesToScan" value="eu.cloudscale.showcase.db.dao" />
+ <property name="hibernateProperties">
+ <props>
+ <prop key="hibernate.hbm2ddl.auto">create</prop>
+ <prop key="hibernate.jdbc.batch_size">50</prop>
+ <prop key="hibernate.show_sql">false</prop>
+ <prop key="hibernate.dialect">${jdbc.hibernate.dialect}</prop>
+ <prop key="hibernate.max_fetch_depth">4</prop>
+ <!-- <prop key="hibernate.connection.release_mode">after_statement</prop> -->
+ <prop key="hibernate.cache.use_second_level_cache">true</prop>
+ <prop key="hibernate.cache.use_query_cache">true</prop>
+ <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
+ </prop>
+ <prop key="hibernate.cache.provider_configuration_file_resource_path">classpath:ehcache.xml</prop>
+ <prop key="hibernate.generate_statistics">true</prop>
+ </props>
+ </property>
+ <property name="annotatedClasses">
+ <list>
+ <value>eu.cloudscale.showcase.db.model.hibernate.Address</value>
+ <value>eu.cloudscale.showcase.db.model.hibernate.Author</value>
+ <value>eu.cloudscale.showcase.db.model.hibernate.CcXacts</value>
+ <value>eu.cloudscale.showcase.db.model.hibernate.Country</value>
+ <value>eu.cloudscale.showcase.db.model.hibernate.Customer</value>
+ <value>eu.cloudscale.showcase.db.model.hibernate.Item</value>
+ <value>eu.cloudscale.showcase.db.model.hibernate.OrderLine</value>
+ <!-- <value>eu.cloudscale.showcase.db.model.rbms.CcXactsId</value> -->
+ <value>eu.cloudscale.showcase.db.model.hibernate.Orders</value>
+ <value>eu.cloudscale.showcase.db.model.hibernate.ShoppingCart
+ </value>
+ <value>eu.cloudscale.showcase.db.model.hibernate.ShoppingCartLine
+ </value>
+ </list>
+ </property>
+ </bean>
+ <bean id="transactionManager"
+ class="org.springframework.orm.hibernate4.HibernateTransactionManager">
+ <property name="sessionFactory" ref="sessionFactory" />
+ </bean>
+</beans>
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/log4j.properties b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/log4j.properties
new file mode 100644
index 0000000..a098bf1
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/log4j.properties
@@ -0,0 +1,7 @@
+log4j.rootCategory=ERROR, stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n
+log4j.category.org.springframework.beans.factory=ERROR
+log4j.logger.com.mchange=INFO
+log4j.category.org.springframework.data.document.mongodb=DEBUG
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/mongodb.xml b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/mongodb.xml
new file mode 100644
index 0000000..deb185c
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/mongodb.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:mongo="http://www.springframework.org/schema/data/mongo"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/data/mongo
+ http://www.springframework.org/schema/data/mongo/spring-mongo.xsd">
+
+ <!-- More information: http://static.springsource.org/spring-data/data-mongodb/docs/current/reference/html/mongo.core.html -->
+ <context:property-placeholder
+ location="classpath:database/database.aws.mongodb.properties" />
+
+ <context:component-scan base-package="eu.cloudscale.showcase.db.dao.mongo.impl" />
+
+ <mongo:mongo host="${mongodb.host}" port="${mongodb.port}" >
+ <mongo:options connections-per-host="100"
+ threads-allowed-to-block-for-connection-multiplier="50"
+ connect-timeout="1000"
+ max-wait-time="2000"
+ auto-connect-retry="true"
+ socket-keep-alive="true"
+ socket-timeout="2000"/>
+ </mongo:mongo>
+
+ <mongo:db-factory host="${mongodb.host}" port="${mongodb.port}"
+ dbname="${mongodb.dbname}" username="${mongodb.username}" password="${mongodb.password}" />
+
+ <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
+ <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
+
+ </bean>
+ <bean id="service" class="eu.cloudscale.showcase.db.services.MongoService">
+ </bean>
+</beans>
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/schema.sql b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/schema.sql
new file mode 100644
index 0000000..ca29ee9
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/resources/schema.sql
@@ -0,0 +1,264 @@
+SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
+SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
+SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL';
+
+DROP SCHEMA IF EXISTS `tpcw` ;
+CREATE SCHEMA IF NOT EXISTS `tpcw` DEFAULT CHARACTER SET utf8 COLLATE utf8_slovenian_ci ;
+USE `tpcw` ;
+
+-- -----------------------------------------------------
+-- Table `tpcw`.`author`
+-- -----------------------------------------------------
+DROP TABLE IF EXISTS `tpcw`.`author` ;
+
+CREATE TABLE IF NOT EXISTS `tpcw`.`author` (
+ `A_ID` INT NOT NULL AUTO_INCREMENT ,
+ `A_FNAME` VARCHAR(20) NULL ,
+ `A_LNAME` VARCHAR(20) NULL ,
+ `A_MNAME` VARCHAR(20) NULL ,
+ `A_DOB` DATETIME NULL ,
+ `A_BIO` TEXT NULL ,
+ PRIMARY KEY (`A_ID`) )
+ENGINE = InnoDB;
+
+
+-- -----------------------------------------------------
+-- Table `tpcw`.`item`
+-- -----------------------------------------------------
+DROP TABLE IF EXISTS `tpcw`.`item` ;
+
+CREATE TABLE IF NOT EXISTS `tpcw`.`item` (
+ `I_ID` INT NOT NULL AUTO_INCREMENT ,
+ `I_TITLE` VARCHAR(60) NULL ,
+ `I_A_ID` INT NOT NULL ,
+ `I_PUB_DATE` DATETIME NULL ,
+ `I_PUBLISHER` VARCHAR(60) NULL ,
+ `I_SUBJECT` VARCHAR(60) NULL ,
+ `I_DESC` TEXT NULL ,
+ `I_RELATED1` INT NULL ,
+ `I_RELATED2` INT NULL ,
+ `I_RELATED3` INT NULL ,
+ `I_RELATED4` INT NULL ,
+ `I_RELATED5` INT NULL ,
+ `I_THUMBNAIL` VARCHAR(60) NULL ,
+ `I_IMAGE` VARCHAR(60) NULL ,
+ `I_SRP` INT NULL ,
+ `I_COST` INT NULL ,
+ `I_AVAIL` DATETIME NULL ,
+ `I_STOCK` INT NULL ,
+ `I_ISBN` VARCHAR(13) NULL ,
+ `I_PAGE` VARCHAR(4) NULL ,
+ `I_BACKING` VARCHAR(15) NULL ,
+ `I_DIMENSION` VARCHAR(25) NULL ,
+ INDEX `fk_ITEM_AUTHOR` (`I_A_ID` ASC) ,
+ PRIMARY KEY (`I_ID`) ,
+ CONSTRAINT `fk_ITEM_AUTHOR`
+ FOREIGN KEY (`I_A_ID` )
+ REFERENCES `tpcw`.`author` (`A_ID` )
+ ON DELETE NO ACTION
+ ON UPDATE NO ACTION)
+ENGINE = InnoDB;
+
+
+-- -----------------------------------------------------
+-- Table `tpcw`.`country`
+-- -----------------------------------------------------
+DROP TABLE IF EXISTS `tpcw`.`country` ;
+
+CREATE TABLE IF NOT EXISTS `tpcw`.`country` (
+ `CO_ID` INT NOT NULL AUTO_INCREMENT ,
+ `CO_NAME` VARCHAR(50) NULL ,
+ `CO_EXCHANGE` DOUBLE NULL ,
+ `CO_CURRENCY` VARCHAR(18) NULL ,
+ PRIMARY KEY (`CO_ID`) )
+ENGINE = InnoDB;
+
+
+-- -----------------------------------------------------
+-- Table `tpcw`.`address`
+-- -----------------------------------------------------
+DROP TABLE IF EXISTS `tpcw`.`address` ;
+
+CREATE TABLE IF NOT EXISTS `tpcw`.`address` (
+ `ADDR_ID` INT NOT NULL AUTO_INCREMENT ,
+ `ADDR_STREET1` VARCHAR(40) NULL ,
+ `ADDR_STREET2` VARCHAR(40) NULL ,
+ `ADDR_CITY` VARCHAR(30) NULL ,
+ `ADDR_STATE` VARCHAR(20) NULL ,
+ `ADDR_ZIP` VARCHAR(10) NULL ,
+ `ADDR_CO_ID` INT NOT NULL ,
+ PRIMARY KEY (`ADDR_ID`) ,
+ INDEX `fk_ADDRESS_COUNTRY1` (`ADDR_CO_ID` ASC) ,
+ CONSTRAINT `fk_ADDRESS_COUNTRY1`
+ FOREIGN KEY (`ADDR_CO_ID` )
+ REFERENCES `tpcw`.`country` (`CO_ID` )
+ ON DELETE NO ACTION
+ ON UPDATE NO ACTION)
+ENGINE = InnoDB;
+
+
+-- -----------------------------------------------------
+-- Table `tpcw`.`customer`
+-- -----------------------------------------------------
+DROP TABLE IF EXISTS `tpcw`.`customer` ;
+
+CREATE TABLE IF NOT EXISTS `tpcw`.`customer` (
+ `C_ID` INT NOT NULL AUTO_INCREMENT ,
+ `C_UNAME` VARCHAR(20) NULL ,
+ `C_PASSWD` VARCHAR(20) NULL ,
+ `C_FNAME` VARCHAR(15) NULL ,
+ `C_LNAME` VARCHAR(15) NULL ,
+ `C_ADDR_ID` INT NOT NULL ,
+ `C_PHONE` VARCHAR(16) NULL ,
+ `C_EMAIL` VARCHAR(50) NULL ,
+ `C_SINCE` DATE NULL ,
+ `C_LAST_VISIT` DATE NULL ,
+ `C_LOGIN` DATETIME NULL ,
+ `C_EXPIRATION` DATETIME NULL COMMENT ' ' ,
+ `C_DISCOUNT` INT NULL ,
+ `C_BALANCE` INT NULL ,
+ `C_YTD_PMT` INT NULL ,
+ `C_BIRTHDATE` DATE NULL ,
+ `C_DATA` TEXT NULL ,
+ PRIMARY KEY (`C_ID`) ,
+ INDEX `fk_CUSTOMER_ADDRESS1` (`C_ADDR_ID` ASC) ,
+ CONSTRAINT `fk_CUSTOMER_ADDRESS1`
+ FOREIGN KEY (`C_ADDR_ID` )
+ REFERENCES `tpcw`.`address` (`ADDR_ID` )
+ ON DELETE NO ACTION
+ ON UPDATE NO ACTION)
+ENGINE = InnoDB;
+
+
+-- -----------------------------------------------------
+-- Table `tpcw`.`orders`
+-- -----------------------------------------------------
+DROP TABLE IF EXISTS `tpcw`.`orders` ;
+
+CREATE TABLE IF NOT EXISTS `tpcw`.`orders` (
+ `O_ID` INT NOT NULL AUTO_INCREMENT ,
+ `O_C_ID` INT NOT NULL ,
+ `O_DATE` DATETIME NULL ,
+ `O_SUB_TOTAL` INT NULL ,
+ `O_TAX` INT NULL ,
+ `O_TOTAL` INT NULL ,
+ `O_SHIP_TYPE` VARCHAR(10) NULL ,
+ `O_SHIP_DATE` DATETIME NULL ,
+ `O_BILL_ADDR_ID` INT NOT NULL ,
+ `O_SHIP_ADDR_ID` INT NOT NULL ,
+ `O_STATUS` VARCHAR(15) NULL ,
+ PRIMARY KEY (`O_ID`) ,
+ INDEX `fk_ORDERS_CUSTOMER1` (`O_C_ID` ASC) ,
+ INDEX `fk_ORDERS_ADDRESS1` (`O_BILL_ADDR_ID` ASC) ,
+ INDEX `fk_ORDERS_ADDRESS2` (`O_SHIP_ADDR_ID` ASC) ,
+ CONSTRAINT `fk_ORDERS_CUSTOMER1`
+ FOREIGN KEY (`O_C_ID` )
+ REFERENCES `tpcw`.`customer` (`C_ID` )
+ ON DELETE NO ACTION
+ ON UPDATE NO ACTION,
+ CONSTRAINT `fk_ORDERS_ADDRESS1`
+ FOREIGN KEY (`O_BILL_ADDR_ID` )
+ REFERENCES `tpcw`.`address` (`ADDR_ID` )
+ ON DELETE NO ACTION
+ ON UPDATE NO ACTION,
+ CONSTRAINT `fk_ORDERS_ADDRESS2`
+ FOREIGN KEY (`O_SHIP_ADDR_ID` )
+ REFERENCES `tpcw`.`address` (`ADDR_ID` )
+ ON DELETE NO ACTION
+ ON UPDATE NO ACTION)
+ENGINE = InnoDB;
+
+
+-- -----------------------------------------------------
+-- Table `tpcw`.`order_line`
+-- -----------------------------------------------------
+DROP TABLE IF EXISTS `tpcw`.`order_line` ;
+
+CREATE TABLE IF NOT EXISTS `tpcw`.`order_line` (
+ `OL_ID` INT NOT NULL ,
+ `OL_O_ID` INT NOT NULL ,
+ `OL_I_ID` INT NOT NULL ,
+ `OL_QTY` INT NULL ,
+ `OL_DISCOUNT` INT NULL ,
+ `OL_COMMENT` VARCHAR(100) NULL ,
+ PRIMARY KEY (`OL_ID`) ,
+ INDEX `fk_ORDER_LINE_ITEM1` (`OL_I_ID` ASC) ,
+ INDEX `fk_ORDER_LINE_ORDERS1` (`OL_O_ID` ASC) ,
+ CONSTRAINT `fk_ORDER_LINE_ITEM1`
+ FOREIGN KEY (`OL_I_ID` )
+ REFERENCES `tpcw`.`item` (`I_ID` )
+ ON DELETE NO ACTION
+ ON UPDATE NO ACTION,
+ CONSTRAINT `fk_ORDER_LINE_ORDERS1`
+ FOREIGN KEY (`OL_O_ID` )
+ REFERENCES `tpcw`.`orders` (`O_ID` )
+ ON DELETE NO ACTION
+ ON UPDATE NO ACTION)
+ENGINE = InnoDB;
+
+
+-- -----------------------------------------------------
+-- Table `tpcw`.`cc_xacts`
+-- -----------------------------------------------------
+DROP TABLE IF EXISTS `tpcw`.`cc_xacts` ;
+
+CREATE TABLE IF NOT EXISTS `tpcw`.`cc_xacts` (
+ `CX_O_ID` INT NOT NULL AUTO_INCREMENT ,
+ `CX_TYPE` VARCHAR(10) NULL ,
+ `CX_NUM` INT NULL ,
+ `CX_NAME` VARCHAR(31) NULL ,
+ `CX_EXPIRY` DATE NULL ,
+ `CX_AUTH_ID` VARCHAR(15) NULL ,
+ `CX_XACT_AMT` DECIMAL(15,2) NULL ,
+ `CX_XACT_DATE` DATETIME NULL ,
+ `CX_CO_ID` INT NOT NULL ,
+ INDEX `fk_CC_XACTS_ORDERS` (`CX_O_ID` ASC) ,
+ INDEX `fk_CC_XACTS_COUNTRY` (`CX_CO_ID` ASC) ,
+ CONSTRAINT `fk_CC_XACTS_ORDERS`
+ FOREIGN KEY (`CX_O_ID` )
+ REFERENCES `tpcw`.`orders` (`O_ID` )
+ ON DELETE NO ACTION
+ ON UPDATE NO ACTION,
+ CONSTRAINT `fk_CC_XACTS_COUNTRY`
+ FOREIGN KEY (`CX_CO_ID` )
+ REFERENCES `tpcw`.`country` (`CO_ID` )
+ ON DELETE NO ACTION
+ ON UPDATE NO ACTION)
+ENGINE = InnoDB;
+
+
+-- -----------------------------------------------------
+-- Table `tpcw`.`shopping_cart`
+-- -----------------------------------------------------
+DROP TABLE IF EXISTS `tpcw`.`shopping_cart` ;
+
+CREATE TABLE IF NOT EXISTS `tpcw`.`shopping_cart` (
+ `SC_ID` INT NOT NULL AUTO_INCREMENT ,
+ `SC_TIME` TIMESTAMP NULL ,
+ PRIMARY KEY (`SC_ID`) )
+ENGINE = InnoDB;
+
+
+-- -----------------------------------------------------
+-- Table `tpcw`.`shopping_cart_line`
+-- -----------------------------------------------------
+DROP TABLE IF EXISTS `tpcw`.`shopping_cart_line` ;
+
+CREATE TABLE IF NOT EXISTS `tpcw`.`shopping_cart_line` (
+ `SCL_SC_ID` INT NOT NULL AUTO_INCREMENT ,
+ `SCL_QTY` INT NULL ,
+ `SCL_I_ID` INT NOT NULL ,
+ PRIMARY KEY (`SCL_SC_ID`) ,
+ INDEX `fk_shopping_cart_line_item1` (`SCL_I_ID` ASC) ,
+ CONSTRAINT `fk_shopping_cart_line_item1`
+ FOREIGN KEY (`SCL_I_ID` )
+ REFERENCES `tpcw`.`item` (`I_ID` )
+ ON DELETE NO ACTION
+ ON UPDATE NO ACTION)
+ENGINE = InnoDB;
+
+
+
+SET SQL_MODE=@OLD_SQL_MODE;
+SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
+SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap.css b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap.css
new file mode 100644
index 0000000..2f56af3
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap.css
@@ -0,0 +1,6158 @@
+/*!
+ * Bootstrap v2.3.1
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */
+
+.clearfix {
+ *zoom: 1;
+}
+
+.clearfix:before,
+.clearfix:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.clearfix:after {
+ clear: both;
+}
+
+.hide-text {
+ font: 0/0 a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0;
+}
+
+.input-block-level {
+ display: block;
+ width: 100%;
+ min-height: 30px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+nav,
+section {
+ display: block;
+}
+
+audio,
+canvas,
+video {
+ display: inline-block;
+ *display: inline;
+ *zoom: 1;
+}
+
+audio:not([controls]) {
+ display: none;
+}
+
+html {
+ font-size: 100%;
+ -webkit-text-size-adjust: 100%;
+ -ms-text-size-adjust: 100%;
+}
+
+a:focus {
+ outline: thin dotted #333;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+
+a:hover,
+a:active {
+ outline: 0;
+}
+
+sub,
+sup {
+ position: relative;
+ font-size: 75%;
+ line-height: 0;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+img {
+ width: auto\9;
+ height: auto;
+ max-width: 100%;
+ vertical-align: middle;
+ border: 0;
+ -ms-interpolation-mode: bicubic;
+}
+
+#map_canvas img,
+.google-maps img {
+ max-width: none;
+}
+
+button,
+input,
+select,
+textarea {
+ margin: 0;
+ font-size: 100%;
+ vertical-align: middle;
+}
+
+button,
+input {
+ *overflow: visible;
+ line-height: normal;
+}
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ padding: 0;
+ border: 0;
+}
+
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+ cursor: pointer;
+ -webkit-appearance: button;
+}
+
+label,
+select,
+button,
+input[type="button"],
+input[type="reset"],
+input[type="submit"],
+input[type="radio"],
+input[type="checkbox"] {
+ cursor: pointer;
+}
+
+input[type="search"] {
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ -webkit-appearance: textfield;
+}
+
+input[type="search"]::-webkit-search-decoration,
+input[type="search"]::-webkit-search-cancel-button {
+ -webkit-appearance: none;
+}
+
+textarea {
+ overflow: auto;
+ vertical-align: top;
+}
+
+@media print {
+ * {
+ color: #000 !important;
+ text-shadow: none !important;
+ background: transparent !important;
+ box-shadow: none !important;
+ }
+ a,
+ a:visited {
+ text-decoration: underline;
+ }
+ a[href]:after {
+ content: " (" attr(href) ")";
+ }
+ abbr[title]:after {
+ content: " (" attr(title) ")";
+ }
+ .ir a:after,
+ a[href^="javascript:"]:after,
+ a[href^="#"]:after {
+ content: "";
+ }
+ pre,
+ blockquote {
+ border: 1px solid #999;
+ page-break-inside: avoid;
+ }
+ thead {
+ display: table-header-group;
+ }
+ tr,
+ img {
+ page-break-inside: avoid;
+ }
+ img {
+ max-width: 100% !important;
+ }
+ @page {
+ margin: 0.5cm;
+ }
+ p,
+ h2,
+ h3 {
+ orphans: 3;
+ widows: 3;
+ }
+ h2,
+ h3 {
+ page-break-after: avoid;
+ }
+}
+
+body {
+ margin: 0;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ line-height: 20px;
+ color: #333333;
+ background-color: #ffffff;
+}
+
+a {
+ color: #0088cc;
+ text-decoration: none;
+}
+
+a:hover,
+a:focus {
+ color: #005580;
+ text-decoration: underline;
+}
+
+.img-rounded {
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+}
+
+.img-polaroid {
+ padding: 4px;
+ background-color: #fff;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+ -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+}
+
+.img-circle {
+ -webkit-border-radius: 500px;
+ -moz-border-radius: 500px;
+ border-radius: 500px;
+}
+
+.row {
+ margin-left: -20px;
+ *zoom: 1;
+}
+
+.row:before,
+.row:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.row:after {
+ clear: both;
+}
+
+[class*="span"] {
+ float: left;
+ min-height: 1px;
+ margin-left: 20px;
+}
+
+.container,
+.navbar-static-top .container,
+.navbar-fixed-top .container,
+.navbar-fixed-bottom .container {
+ width: 940px;
+}
+
+.span12 {
+ width: 940px;
+}
+
+.span11 {
+ width: 860px;
+}
+
+.span10 {
+ width: 780px;
+}
+
+.span9 {
+ width: 700px;
+}
+
+.span8 {
+ width: 620px;
+}
+
+.span7 {
+ width: 540px;
+}
+
+.span6 {
+ width: 460px;
+}
+
+.span5 {
+ width: 380px;
+}
+
+.span4 {
+ width: 300px;
+}
+
+.span3 {
+ width: 220px;
+}
+
+.span2 {
+ width: 140px;
+}
+
+.span1 {
+ width: 60px;
+}
+
+.offset12 {
+ margin-left: 980px;
+}
+
+.offset11 {
+ margin-left: 900px;
+}
+
+.offset10 {
+ margin-left: 820px;
+}
+
+.offset9 {
+ margin-left: 740px;
+}
+
+.offset8 {
+ margin-left: 660px;
+}
+
+.offset7 {
+ margin-left: 580px;
+}
+
+.offset6 {
+ margin-left: 500px;
+}
+
+.offset5 {
+ margin-left: 420px;
+}
+
+.offset4 {
+ margin-left: 340px;
+}
+
+.offset3 {
+ margin-left: 260px;
+}
+
+.offset2 {
+ margin-left: 180px;
+}
+
+.offset1 {
+ margin-left: 100px;
+}
+
+.row-fluid {
+ width: 100%;
+ *zoom: 1;
+}
+
+.row-fluid:before,
+.row-fluid:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.row-fluid:after {
+ clear: both;
+}
+
+.row-fluid [class*="span"] {
+ display: block;
+ float: left;
+ width: 100%;
+ min-height: 30px;
+ margin-left: 2.127659574468085%;
+ *margin-left: 2.074468085106383%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+.row-fluid [class*="span"]:first-child {
+ margin-left: 0;
+}
+
+.row-fluid .controls-row [class*="span"] + [class*="span"] {
+ margin-left: 2.127659574468085%;
+}
+
+.row-fluid .span12 {
+ width: 100%;
+ *width: 99.94680851063829%;
+}
+
+.row-fluid .span11 {
+ width: 91.48936170212765%;
+ *width: 91.43617021276594%;
+}
+
+.row-fluid .span10 {
+ width: 82.97872340425532%;
+ *width: 82.92553191489361%;
+}
+
+.row-fluid .span9 {
+ width: 74.46808510638297%;
+ *width: 74.41489361702126%;
+}
+
+.row-fluid .span8 {
+ width: 65.95744680851064%;
+ *width: 65.90425531914893%;
+}
+
+.row-fluid .span7 {
+ width: 57.44680851063829%;
+ *width: 57.39361702127659%;
+}
+
+.row-fluid .span6 {
+ width: 48.93617021276595%;
+ *width: 48.88297872340425%;
+}
+
+.row-fluid .span5 {
+ width: 40.42553191489362%;
+ *width: 40.37234042553192%;
+}
+
+.row-fluid .span4 {
+ width: 31.914893617021278%;
+ *width: 31.861702127659576%;
+}
+
+.row-fluid .span3 {
+ width: 23.404255319148934%;
+ *width: 23.351063829787233%;
+}
+
+.row-fluid .span2 {
+ width: 14.893617021276595%;
+ *width: 14.840425531914894%;
+}
+
+.row-fluid .span1 {
+ width: 6.382978723404255%;
+ *width: 6.329787234042553%;
+}
+
+.row-fluid .offset12 {
+ margin-left: 104.25531914893617%;
+ *margin-left: 104.14893617021275%;
+}
+
+.row-fluid .offset12:first-child {
+ margin-left: 102.12765957446808%;
+ *margin-left: 102.02127659574467%;
+}
+
+.row-fluid .offset11 {
+ margin-left: 95.74468085106382%;
+ *margin-left: 95.6382978723404%;
+}
+
+.row-fluid .offset11:first-child {
+ margin-left: 93.61702127659574%;
+ *margin-left: 93.51063829787232%;
+}
+
+.row-fluid .offset10 {
+ margin-left: 87.23404255319149%;
+ *margin-left: 87.12765957446807%;
+}
+
+.row-fluid .offset10:first-child {
+ margin-left: 85.1063829787234%;
+ *margin-left: 84.99999999999999%;
+}
+
+.row-fluid .offset9 {
+ margin-left: 78.72340425531914%;
+ *margin-left: 78.61702127659572%;
+}
+
+.row-fluid .offset9:first-child {
+ margin-left: 76.59574468085106%;
+ *margin-left: 76.48936170212764%;
+}
+
+.row-fluid .offset8 {
+ margin-left: 70.2127659574468%;
+ *margin-left: 70.10638297872339%;
+}
+
+.row-fluid .offset8:first-child {
+ margin-left: 68.08510638297872%;
+ *margin-left: 67.9787234042553%;
+}
+
+.row-fluid .offset7 {
+ margin-left: 61.70212765957446%;
+ *margin-left: 61.59574468085106%;
+}
+
+.row-fluid .offset7:first-child {
+ margin-left: 59.574468085106375%;
+ *margin-left: 59.46808510638297%;
+}
+
+.row-fluid .offset6 {
+ margin-left: 53.191489361702125%;
+ *margin-left: 53.085106382978715%;
+}
+
+.row-fluid .offset6:first-child {
+ margin-left: 51.063829787234035%;
+ *margin-left: 50.95744680851063%;
+}
+
+.row-fluid .offset5 {
+ margin-left: 44.68085106382979%;
+ *margin-left: 44.57446808510638%;
+}
+
+.row-fluid .offset5:first-child {
+ margin-left: 42.5531914893617%;
+ *margin-left: 42.4468085106383%;
+}
+
+.row-fluid .offset4 {
+ margin-left: 36.170212765957444%;
+ *margin-left: 36.06382978723405%;
+}
+
+.row-fluid .offset4:first-child {
+ margin-left: 34.04255319148936%;
+ *margin-left: 33.93617021276596%;
+}
+
+.row-fluid .offset3 {
+ margin-left: 27.659574468085104%;
+ *margin-left: 27.5531914893617%;
+}
+
+.row-fluid .offset3:first-child {
+ margin-left: 25.53191489361702%;
+ *margin-left: 25.425531914893618%;
+}
+
+.row-fluid .offset2 {
+ margin-left: 19.148936170212764%;
+ *margin-left: 19.04255319148936%;
+}
+
+.row-fluid .offset2:first-child {
+ margin-left: 17.02127659574468%;
+ *margin-left: 16.914893617021278%;
+}
+
+.row-fluid .offset1 {
+ margin-left: 10.638297872340425%;
+ *margin-left: 10.53191489361702%;
+}
+
+.row-fluid .offset1:first-child {
+ margin-left: 8.51063829787234%;
+ *margin-left: 8.404255319148938%;
+}
+
+[class*="span"].hide,
+.row-fluid [class*="span"].hide {
+ display: none;
+}
+
+[class*="span"].pull-right,
+.row-fluid [class*="span"].pull-right {
+ float: right;
+}
+
+.container {
+ margin-right: auto;
+ margin-left: auto;
+ *zoom: 1;
+}
+
+.container:before,
+.container:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.container:after {
+ clear: both;
+}
+
+.container-fluid {
+ padding-right: 20px;
+ padding-left: 20px;
+ *zoom: 1;
+}
+
+.container-fluid:before,
+.container-fluid:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.container-fluid:after {
+ clear: both;
+}
+
+p {
+ margin: 0 0 10px;
+}
+
+.lead {
+ margin-bottom: 20px;
+ font-size: 21px;
+ font-weight: 200;
+ line-height: 30px;
+}
+
+small {
+ font-size: 85%;
+}
+
+strong {
+ font-weight: bold;
+}
+
+em {
+ font-style: italic;
+}
+
+cite {
+ font-style: normal;
+}
+
+.muted {
+ color: #999999;
+}
+
+a.muted:hover,
+a.muted:focus {
+ color: #808080;
+}
+
+.text-warning {
+ color: #c09853;
+}
+
+a.text-warning:hover,
+a.text-warning:focus {
+ color: #a47e3c;
+}
+
+.text-error {
+ color: #b94a48;
+}
+
+a.text-error:hover,
+a.text-error:focus {
+ color: #953b39;
+}
+
+.text-info {
+ color: #3a87ad;
+}
+
+a.text-info:hover,
+a.text-info:focus {
+ color: #2d6987;
+}
+
+.text-success {
+ color: #468847;
+}
+
+a.text-success:hover,
+a.text-success:focus {
+ color: #356635;
+}
+
+.text-left {
+ text-align: left;
+}
+
+.text-right {
+ text-align: right;
+}
+
+.text-center {
+ text-align: center;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ margin: 10px 0;
+ font-family: inherit;
+ font-weight: bold;
+ line-height: 20px;
+ color: inherit;
+ text-rendering: optimizelegibility;
+}
+
+h1 small,
+h2 small,
+h3 small,
+h4 small,
+h5 small,
+h6 small {
+ font-weight: normal;
+ line-height: 1;
+ color: #999999;
+}
+
+h1,
+h2,
+h3 {
+ line-height: 40px;
+}
+
+h1 {
+ font-size: 38.5px;
+}
+
+h2 {
+ font-size: 31.5px;
+}
+
+h3 {
+ font-size: 24.5px;
+}
+
+h4 {
+ font-size: 17.5px;
+}
+
+h5 {
+ font-size: 14px;
+}
+
+h6 {
+ font-size: 11.9px;
+}
+
+h1 small {
+ font-size: 24.5px;
+}
+
+h2 small {
+ font-size: 17.5px;
+}
+
+h3 small {
+ font-size: 14px;
+}
+
+h4 small {
+ font-size: 14px;
+}
+
+.page-header {
+ padding-bottom: 9px;
+ margin: 20px 0 30px;
+ border-bottom: 1px solid #eeeeee;
+}
+
+ul,
+ol {
+ padding: 0;
+ margin: 0 0 10px 25px;
+}
+
+ul ul,
+ul ol,
+ol ol,
+ol ul {
+ margin-bottom: 0;
+}
+
+li {
+ line-height: 20px;
+}
+
+ul.unstyled,
+ol.unstyled {
+ margin-left: 0;
+ list-style: none;
+}
+
+ul.inline,
+ol.inline {
+ margin-left: 0;
+ list-style: none;
+}
+
+ul.inline > li,
+ol.inline > li {
+ display: inline-block;
+ *display: inline;
+ padding-right: 5px;
+ padding-left: 5px;
+ *zoom: 1;
+}
+
+dl {
+ margin-bottom: 20px;
+}
+
+dt,
+dd {
+ line-height: 20px;
+}
+
+dt {
+ font-weight: bold;
+}
+
+dd {
+ margin-left: 10px;
+}
+
+.dl-horizontal {
+ *zoom: 1;
+}
+
+.dl-horizontal:before,
+.dl-horizontal:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.dl-horizontal:after {
+ clear: both;
+}
+
+.dl-horizontal dt {
+ float: left;
+ width: 160px;
+ overflow: hidden;
+ clear: left;
+ text-align: right;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.dl-horizontal dd {
+ margin-left: 180px;
+}
+
+hr {
+ margin: 20px 0;
+ border: 0;
+ border-top: 1px solid #eeeeee;
+ border-bottom: 1px solid #ffffff;
+}
+
+abbr[title],
+abbr[data-original-title] {
+ cursor: help;
+ border-bottom: 1px dotted #999999;
+}
+
+abbr.initialism {
+ font-size: 90%;
+ text-transform: uppercase;
+}
+
+blockquote {
+ padding: 0 0 0 15px;
+ margin: 0 0 20px;
+ border-left: 5px solid #eeeeee;
+}
+
+blockquote p {
+ margin-bottom: 0;
+ font-size: 17.5px;
+ font-weight: 300;
+ line-height: 1.25;
+}
+
+blockquote small {
+ display: block;
+ line-height: 20px;
+ color: #999999;
+}
+
+blockquote small:before {
+ content: '\2014 \00A0';
+}
+
+blockquote.pull-right {
+ float: right;
+ padding-right: 15px;
+ padding-left: 0;
+ border-right: 5px solid #eeeeee;
+ border-left: 0;
+}
+
+blockquote.pull-right p,
+blockquote.pull-right small {
+ text-align: right;
+}
+
+blockquote.pull-right small:before {
+ content: '';
+}
+
+blockquote.pull-right small:after {
+ content: '\00A0 \2014';
+}
+
+q:before,
+q:after,
+blockquote:before,
+blockquote:after {
+ content: "";
+}
+
+address {
+ display: block;
+ margin-bottom: 20px;
+ font-style: normal;
+ line-height: 20px;
+}
+
+code,
+pre {
+ padding: 0 3px 2px;
+ font-family: Monaco, Menlo, Consolas, "Courier New", monospace;
+ font-size: 12px;
+ color: #333333;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+
+code {
+ padding: 2px 4px;
+ color: #d14;
+ white-space: nowrap;
+ background-color: #f7f7f9;
+ border: 1px solid #e1e1e8;
+}
+
+pre {
+ display: block;
+ padding: 9.5px;
+ margin: 0 0 10px;
+ font-size: 13px;
+ line-height: 20px;
+ word-break: break-all;
+ word-wrap: break-word;
+ white-space: pre;
+ white-space: pre-wrap;
+ background-color: #f5f5f5;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+pre.prettyprint {
+ margin-bottom: 20px;
+}
+
+pre code {
+ padding: 0;
+ color: inherit;
+ white-space: pre;
+ white-space: pre-wrap;
+ background-color: transparent;
+ border: 0;
+}
+
+.pre-scrollable {
+ max-height: 340px;
+ overflow-y: scroll;
+}
+
+form {
+ margin: 0 0 20px;
+}
+
+fieldset {
+ padding: 0;
+ margin: 0;
+ border: 0;
+}
+
+legend {
+ display: block;
+ width: 100%;
+ padding: 0;
+ margin-bottom: 20px;
+ font-size: 21px;
+ line-height: 40px;
+ color: #333333;
+ border: 0;
+ border-bottom: 1px solid #e5e5e5;
+}
+
+legend small {
+ font-size: 15px;
+ color: #999999;
+}
+
+label,
+input,
+button,
+select,
+textarea {
+ font-size: 14px;
+ font-weight: normal;
+ line-height: 20px;
+}
+
+input,
+button,
+select,
+textarea {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+
+label {
+ display: block;
+ margin-bottom: 5px;
+}
+
+select,
+textarea,
+input[type="text"],
+input[type="password"],
+input[type="datetime"],
+input[type="datetime-local"],
+input[type="date"],
+input[type="month"],
+input[type="time"],
+input[type="week"],
+input[type="number"],
+input[type="email"],
+input[type="url"],
+input[type="search"],
+input[type="tel"],
+input[type="color"],
+.uneditable-input {
+ display: inline-block;
+ height: 20px;
+ padding: 4px 6px;
+ margin-bottom: 10px;
+ font-size: 14px;
+ line-height: 20px;
+ color: #555555;
+ vertical-align: middle;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+input,
+textarea,
+.uneditable-input {
+ width: 206px;
+}
+
+textarea {
+ height: auto;
+}
+
+textarea,
+input[type="text"],
+input[type="password"],
+input[type="datetime"],
+input[type="datetime-local"],
+input[type="date"],
+input[type="month"],
+input[type="time"],
+input[type="week"],
+input[type="number"],
+input[type="email"],
+input[type="url"],
+input[type="search"],
+input[type="tel"],
+input[type="color"],
+.uneditable-input {
+ background-color: #ffffff;
+ border: 1px solid #cccccc;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
+ -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
+ -o-transition: border linear 0.2s, box-shadow linear 0.2s;
+ transition: border linear 0.2s, box-shadow linear 0.2s;
+}
+
+textarea:focus,
+input[type="text"]:focus,
+input[type="password"]:focus,
+input[type="datetime"]:focus,
+input[type="datetime-local"]:focus,
+input[type="date"]:focus,
+input[type="month"]:focus,
+input[type="time"]:focus,
+input[type="week"]:focus,
+input[type="number"]:focus,
+input[type="email"]:focus,
+input[type="url"]:focus,
+input[type="search"]:focus,
+input[type="tel"]:focus,
+input[type="color"]:focus,
+.uneditable-input:focus {
+ border-color: rgba(82, 168, 236, 0.8);
+ outline: 0;
+ outline: thin dotted \9;
+ /* IE6-9 */
+
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
+}
+
+input[type="radio"],
+input[type="checkbox"] {
+ margin: 4px 0 0;
+ margin-top: 1px \9;
+ *margin-top: 0;
+ line-height: normal;
+}
+
+input[type="file"],
+input[type="image"],
+input[type="submit"],
+input[type="reset"],
+input[type="button"],
+input[type="radio"],
+input[type="checkbox"] {
+ width: auto;
+}
+
+select,
+input[type="file"] {
+ height: 30px;
+ /* In IE7, the height of the select element cannot be changed by height, only font-size */
+
+ *margin-top: 4px;
+ /* For IE7, add top margin to align select with labels */
+
+ line-height: 30px;
+}
+
+select {
+ width: 220px;
+ background-color: #ffffff;
+ border: 1px solid #cccccc;
+}
+
+select[multiple],
+select[size] {
+ height: auto;
+}
+
+select:focus,
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus {
+ outline: thin dotted #333;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+
+.uneditable-input,
+.uneditable-textarea {
+ color: #999999;
+ cursor: not-allowed;
+ background-color: #fcfcfc;
+ border-color: #cccccc;
+ -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
+ -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
+}
+
+.uneditable-input {
+ overflow: hidden;
+ white-space: nowrap;
+}
+
+.uneditable-textarea {
+ width: auto;
+ height: auto;
+}
+
+input:-moz-placeholder,
+textarea:-moz-placeholder {
+ color: #999999;
+}
+
+input:-ms-input-placeholder,
+textarea:-ms-input-placeholder {
+ color: #999999;
+}
+
+input::-webkit-input-placeholder,
+textarea::-webkit-input-placeholder {
+ color: #999999;
+}
+
+.radio,
+.checkbox {
+ min-height: 20px;
+ padding-left: 20px;
+}
+
+.radio input[type="radio"],
+.checkbox input[type="checkbox"] {
+ float: left;
+ margin-left: -20px;
+}
+
+.controls > .radio:first-child,
+.controls > .checkbox:first-child {
+ padding-top: 5px;
+}
+
+.radio.inline,
+.checkbox.inline {
+ display: inline-block;
+ padding-top: 5px;
+ margin-bottom: 0;
+ vertical-align: middle;
+}
+
+.radio.inline + .radio.inline,
+.checkbox.inline + .checkbox.inline {
+ margin-left: 10px;
+}
+
+.input-mini {
+ width: 60px;
+}
+
+.input-small {
+ width: 90px;
+}
+
+.input-medium {
+ width: 150px;
+}
+
+.input-large {
+ width: 210px;
+}
+
+.input-xlarge {
+ width: 270px;
+}
+
+.input-xxlarge {
+ width: 530px;
+}
+
+input[class*="span"],
+select[class*="span"],
+textarea[class*="span"],
+.uneditable-input[class*="span"],
+.row-fluid input[class*="span"],
+.row-fluid select[class*="span"],
+.row-fluid textarea[class*="span"],
+.row-fluid .uneditable-input[class*="span"] {
+ float: none;
+ margin-left: 0;
+}
+
+.input-append input[class*="span"],
+.input-append .uneditable-input[class*="span"],
+.input-prepend input[class*="span"],
+.input-prepend .uneditable-input[class*="span"],
+.row-fluid input[class*="span"],
+.row-fluid select[class*="span"],
+.row-fluid textarea[class*="span"],
+.row-fluid .uneditable-input[class*="span"],
+.row-fluid .input-prepend [class*="span"],
+.row-fluid .input-append [class*="span"] {
+ display: inline-block;
+}
+
+input,
+textarea,
+.uneditable-input {
+ margin-left: 0;
+}
+
+.controls-row [class*="span"] + [class*="span"] {
+ margin-left: 20px;
+}
+
+input.span12,
+textarea.span12,
+.uneditable-input.span12 {
+ width: 926px;
+}
+
+input.span11,
+textarea.span11,
+.uneditable-input.span11 {
+ width: 846px;
+}
+
+input.span10,
+textarea.span10,
+.uneditable-input.span10 {
+ width: 766px;
+}
+
+input.span9,
+textarea.span9,
+.uneditable-input.span9 {
+ width: 686px;
+}
+
+input.span8,
+textarea.span8,
+.uneditable-input.span8 {
+ width: 606px;
+}
+
+input.span7,
+textarea.span7,
+.uneditable-input.span7 {
+ width: 526px;
+}
+
+input.span6,
+textarea.span6,
+.uneditable-input.span6 {
+ width: 446px;
+}
+
+input.span5,
+textarea.span5,
+.uneditable-input.span5 {
+ width: 366px;
+}
+
+input.span4,
+textarea.span4,
+.uneditable-input.span4 {
+ width: 286px;
+}
+
+input.span3,
+textarea.span3,
+.uneditable-input.span3 {
+ width: 206px;
+}
+
+input.span2,
+textarea.span2,
+.uneditable-input.span2 {
+ width: 126px;
+}
+
+input.span1,
+textarea.span1,
+.uneditable-input.span1 {
+ width: 46px;
+}
+
+.controls-row {
+ *zoom: 1;
+}
+
+.controls-row:before,
+.controls-row:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.controls-row:after {
+ clear: both;
+}
+
+.controls-row [class*="span"],
+.row-fluid .controls-row [class*="span"] {
+ float: left;
+}
+
+.controls-row .checkbox[class*="span"],
+.controls-row .radio[class*="span"] {
+ padding-top: 5px;
+}
+
+input[disabled],
+select[disabled],
+textarea[disabled],
+input[readonly],
+select[readonly],
+textarea[readonly] {
+ cursor: not-allowed;
+ background-color: #eeeeee;
+}
+
+input[type="radio"][disabled],
+input[type="checkbox"][disabled],
+input[type="radio"][readonly],
+input[type="checkbox"][readonly] {
+ background-color: transparent;
+}
+
+.control-group.warning .control-label,
+.control-group.warning .help-block,
+.control-group.warning .help-inline {
+ color: #c09853;
+}
+
+.control-group.warning .checkbox,
+.control-group.warning .radio,
+.control-group.warning input,
+.control-group.warning select,
+.control-group.warning textarea {
+ color: #c09853;
+}
+
+.control-group.warning input,
+.control-group.warning select,
+.control-group.warning textarea {
+ border-color: #c09853;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.warning input:focus,
+.control-group.warning select:focus,
+.control-group.warning textarea:focus {
+ border-color: #a47e3c;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
+}
+
+.control-group.warning .input-prepend .add-on,
+.control-group.warning .input-append .add-on {
+ color: #c09853;
+ background-color: #fcf8e3;
+ border-color: #c09853;
+}
+
+.control-group.error .control-label,
+.control-group.error .help-block,
+.control-group.error .help-inline {
+ color: #b94a48;
+}
+
+.control-group.error .checkbox,
+.control-group.error .radio,
+.control-group.error input,
+.control-group.error select,
+.control-group.error textarea {
+ color: #b94a48;
+}
+
+.control-group.error input,
+.control-group.error select,
+.control-group.error textarea {
+ border-color: #b94a48;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.error input:focus,
+.control-group.error select:focus,
+.control-group.error textarea:focus {
+ border-color: #953b39;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
+}
+
+.control-group.error .input-prepend .add-on,
+.control-group.error .input-append .add-on {
+ color: #b94a48;
+ background-color: #f2dede;
+ border-color: #b94a48;
+}
+
+.control-group.success .control-label,
+.control-group.success .help-block,
+.control-group.success .help-inline {
+ color: #468847;
+}
+
+.control-group.success .checkbox,
+.control-group.success .radio,
+.control-group.success input,
+.control-group.success select,
+.control-group.success textarea {
+ color: #468847;
+}
+
+.control-group.success input,
+.control-group.success select,
+.control-group.success textarea {
+ border-color: #468847;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.success input:focus,
+.control-group.success select:focus,
+.control-group.success textarea:focus {
+ border-color: #356635;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
+}
+
+.control-group.success .input-prepend .add-on,
+.control-group.success .input-append .add-on {
+ color: #468847;
+ background-color: #dff0d8;
+ border-color: #468847;
+}
+
+.control-group.info .control-label,
+.control-group.info .help-block,
+.control-group.info .help-inline {
+ color: #3a87ad;
+}
+
+.control-group.info .checkbox,
+.control-group.info .radio,
+.control-group.info input,
+.control-group.info select,
+.control-group.info textarea {
+ color: #3a87ad;
+}
+
+.control-group.info input,
+.control-group.info select,
+.control-group.info textarea {
+ border-color: #3a87ad;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+
+.control-group.info input:focus,
+.control-group.info select:focus,
+.control-group.info textarea:focus {
+ border-color: #2d6987;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
+}
+
+.control-group.info .input-prepend .add-on,
+.control-group.info .input-append .add-on {
+ color: #3a87ad;
+ background-color: #d9edf7;
+ border-color: #3a87ad;
+}
+
+input:focus:invalid,
+textarea:focus:invalid,
+select:focus:invalid {
+ color: #b94a48;
+ border-color: #ee5f5b;
+}
+
+input:focus:invalid:focus,
+textarea:focus:invalid:focus,
+select:focus:invalid:focus {
+ border-color: #e9322d;
+ -webkit-box-shadow: 0 0 6px #f8b9b7;
+ -moz-box-shadow: 0 0 6px #f8b9b7;
+ box-shadow: 0 0 6px #f8b9b7;
+}
+
+.form-actions {
+ padding: 19px 20px 20px;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ background-color: #f5f5f5;
+ border-top: 1px solid #e5e5e5;
+ *zoom: 1;
+}
+
+.form-actions:before,
+.form-actions:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.form-actions:after {
+ clear: both;
+}
+
+.help-block,
+.help-inline {
+ color: #595959;
+}
+
+.help-block {
+ display: block;
+ margin-bottom: 10px;
+}
+
+.help-inline {
+ display: inline-block;
+ *display: inline;
+ padding-left: 5px;
+ vertical-align: middle;
+ *zoom: 1;
+}
+
+.input-append,
+.input-prepend {
+ display: inline-block;
+ margin-bottom: 10px;
+ font-size: 0;
+ white-space: nowrap;
+ vertical-align: middle;
+}
+
+.input-append input,
+.input-prepend input,
+.input-append select,
+.input-prepend select,
+.input-append .uneditable-input,
+.input-prepend .uneditable-input,
+.input-append .dropdown-menu,
+.input-prepend .dropdown-menu,
+.input-append .popover,
+.input-prepend .popover {
+ font-size: 14px;
+}
+
+.input-append input,
+.input-prepend input,
+.input-append select,
+.input-prepend select,
+.input-append .uneditable-input,
+.input-prepend .uneditable-input {
+ position: relative;
+ margin-bottom: 0;
+ *margin-left: 0;
+ vertical-align: top;
+ -webkit-border-radius: 0 4px 4px 0;
+ -moz-border-radius: 0 4px 4px 0;
+ border-radius: 0 4px 4px 0;
+}
+
+.input-append input:focus,
+.input-prepend input:focus,
+.input-append select:focus,
+.input-prepend select:focus,
+.input-append .uneditable-input:focus,
+.input-prepend .uneditable-input:focus {
+ z-index: 2;
+}
+
+.input-append .add-on,
+.input-prepend .add-on {
+ display: inline-block;
+ width: auto;
+ height: 20px;
+ min-width: 16px;
+ padding: 4px 5px;
+ font-size: 14px;
+ font-weight: normal;
+ line-height: 20px;
+ text-align: center;
+ text-shadow: 0 1px 0 #ffffff;
+ background-color: #eeeeee;
+ border: 1px solid #ccc;
+}
+
+.input-append .add-on,
+.input-prepend .add-on,
+.input-append .btn,
+.input-prepend .btn,
+.input-append .btn-group > .dropdown-toggle,
+.input-prepend .btn-group > .dropdown-toggle {
+ vertical-align: top;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.input-append .active,
+.input-prepend .active {
+ background-color: #a9dba9;
+ border-color: #46a546;
+}
+
+.input-prepend .add-on,
+.input-prepend .btn {
+ margin-right: -1px;
+}
+
+.input-prepend .add-on:first-child,
+.input-prepend .btn:first-child {
+ -webkit-border-radius: 4px 0 0 4px;
+ -moz-border-radius: 4px 0 0 4px;
+ border-radius: 4px 0 0 4px;
+}
+
+.input-append input,
+.input-append select,
+.input-append .uneditable-input {
+ -webkit-border-radius: 4px 0 0 4px;
+ -moz-border-radius: 4px 0 0 4px;
+ border-radius: 4px 0 0 4px;
+}
+
+.input-append input + .btn-group .btn:last-child,
+.input-append select + .btn-group .btn:last-child,
+.input-append .uneditable-input + .btn-group .btn:last-child {
+ -webkit-border-radius: 0 4px 4px 0;
+ -moz-border-radius: 0 4px 4px 0;
+ border-radius: 0 4px 4px 0;
+}
+
+.input-append .add-on,
+.input-append .btn,
+.input-append .btn-group {
+ margin-left: -1px;
+}
+
+.input-append .add-on:last-child,
+.input-append .btn:last-child,
+.input-append .btn-group:last-child > .dropdown-toggle {
+ -webkit-border-radius: 0 4px 4px 0;
+ -moz-border-radius: 0 4px 4px 0;
+ border-radius: 0 4px 4px 0;
+}
+
+.input-prepend.input-append input,
+.input-prepend.input-append select,
+.input-prepend.input-append .uneditable-input {
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.input-prepend.input-append input + .btn-group .btn,
+.input-prepend.input-append select + .btn-group .btn,
+.input-prepend.input-append .uneditable-input + .btn-group .btn {
+ -webkit-border-radius: 0 4px 4px 0;
+ -moz-border-radius: 0 4px 4px 0;
+ border-radius: 0 4px 4px 0;
+}
+
+.input-prepend.input-append .add-on:first-child,
+.input-prepend.input-append .btn:first-child {
+ margin-right: -1px;
+ -webkit-border-radius: 4px 0 0 4px;
+ -moz-border-radius: 4px 0 0 4px;
+ border-radius: 4px 0 0 4px;
+}
+
+.input-prepend.input-append .add-on:last-child,
+.input-prepend.input-append .btn:last-child {
+ margin-left: -1px;
+ -webkit-border-radius: 0 4px 4px 0;
+ -moz-border-radius: 0 4px 4px 0;
+ border-radius: 0 4px 4px 0;
+}
+
+.input-prepend.input-append .btn-group:first-child {
+ margin-left: 0;
+}
+
+input.search-query {
+ padding-right: 14px;
+ padding-right: 4px \9;
+ padding-left: 14px;
+ padding-left: 4px \9;
+ /* IE7-8 doesn't have border-radius, so don't indent the padding */
+
+ margin-bottom: 0;
+ -webkit-border-radius: 15px;
+ -moz-border-radius: 15px;
+ border-radius: 15px;
+}
+
+/* Allow for input prepend/append in search forms */
+
+.form-search .input-append .search-query,
+.form-search .input-prepend .search-query {
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.form-search .input-append .search-query {
+ -webkit-border-radius: 14px 0 0 14px;
+ -moz-border-radius: 14px 0 0 14px;
+ border-radius: 14px 0 0 14px;
+}
+
+.form-search .input-append .btn {
+ -webkit-border-radius: 0 14px 14px 0;
+ -moz-border-radius: 0 14px 14px 0;
+ border-radius: 0 14px 14px 0;
+}
+
+.form-search .input-prepend .search-query {
+ -webkit-border-radius: 0 14px 14px 0;
+ -moz-border-radius: 0 14px 14px 0;
+ border-radius: 0 14px 14px 0;
+}
+
+.form-search .input-prepend .btn {
+ -webkit-border-radius: 14px 0 0 14px;
+ -moz-border-radius: 14px 0 0 14px;
+ border-radius: 14px 0 0 14px;
+}
+
+.form-search input,
+.form-inline input,
+.form-horizontal input,
+.form-search textarea,
+.form-inline textarea,
+.form-horizontal textarea,
+.form-search select,
+.form-inline select,
+.form-horizontal select,
+.form-search .help-inline,
+.form-inline .help-inline,
+.form-horizontal .help-inline,
+.form-search .uneditable-input,
+.form-inline .uneditable-input,
+.form-horizontal .uneditable-input,
+.form-search .input-prepend,
+.form-inline .input-prepend,
+.form-horizontal .input-prepend,
+.form-search .input-append,
+.form-inline .input-append,
+.form-horizontal .input-append {
+ display: inline-block;
+ *display: inline;
+ margin-bottom: 0;
+ vertical-align: middle;
+ *zoom: 1;
+}
+
+.form-search .hide,
+.form-inline .hide,
+.form-horizontal .hide {
+ display: none;
+}
+
+.form-search label,
+.form-inline label,
+.form-search .btn-group,
+.form-inline .btn-group {
+ display: inline-block;
+}
+
+.form-search .input-append,
+.form-inline .input-append,
+.form-search .input-prepend,
+.form-inline .input-prepend {
+ margin-bottom: 0;
+}
+
+.form-search .radio,
+.form-search .checkbox,
+.form-inline .radio,
+.form-inline .checkbox {
+ padding-left: 0;
+ margin-bottom: 0;
+ vertical-align: middle;
+}
+
+.form-search .radio input[type="radio"],
+.form-search .checkbox input[type="checkbox"],
+.form-inline .radio input[type="radio"],
+.form-inline .checkbox input[type="checkbox"] {
+ float: left;
+ margin-right: 3px;
+ margin-left: 0;
+}
+
+.control-group {
+ margin-bottom: 10px;
+}
+
+legend + .control-group {
+ margin-top: 20px;
+ -webkit-margin-top-collapse: separate;
+}
+
+.form-horizontal .control-group {
+ margin-bottom: 20px;
+ *zoom: 1;
+}
+
+.form-horizontal .control-group:before,
+.form-horizontal .control-group:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.form-horizontal .control-group:after {
+ clear: both;
+}
+
+.form-horizontal .control-label {
+ float: left;
+ width: 160px;
+ padding-top: 5px;
+ text-align: right;
+}
+
+.form-horizontal .controls {
+ *display: inline-block;
+ *padding-left: 20px;
+ margin-left: 180px;
+ *margin-left: 0;
+}
+
+.form-horizontal .controls:first-child {
+ *padding-left: 180px;
+}
+
+.form-horizontal .help-block {
+ margin-bottom: 0;
+}
+
+.form-horizontal input + .help-block,
+.form-horizontal select + .help-block,
+.form-horizontal textarea + .help-block,
+.form-horizontal .uneditable-input + .help-block,
+.form-horizontal .input-prepend + .help-block,
+.form-horizontal .input-append + .help-block {
+ margin-top: 10px;
+}
+
+.form-horizontal .form-actions {
+ padding-left: 180px;
+}
+
+table {
+ max-width: 100%;
+ background-color: transparent;
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+.table {
+ width: 100%;
+ margin-bottom: 20px;
+}
+
+.table th,
+.table td {
+ padding: 8px;
+ line-height: 20px;
+ text-align: left;
+ vertical-align: top;
+ border-top: 1px solid #dddddd;
+}
+
+.table th {
+ font-weight: bold;
+}
+
+.table thead th {
+ vertical-align: bottom;
+}
+
+.table caption + thead tr:first-child th,
+.table caption + thead tr:first-child td,
+.table colgroup + thead tr:first-child th,
+.table colgroup + thead tr:first-child td,
+.table thead:first-child tr:first-child th,
+.table thead:first-child tr:first-child td {
+ border-top: 0;
+}
+
+.table tbody + tbody {
+ border-top: 2px solid #dddddd;
+}
+
+.table .table {
+ background-color: #ffffff;
+}
+
+.table-condensed th,
+.table-condensed td {
+ padding: 4px 5px;
+}
+
+.table-bordered {
+ border: 1px solid #dddddd;
+ border-collapse: separate;
+ *border-collapse: collapse;
+ border-left: 0;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.table-bordered th,
+.table-bordered td {
+ border-left: 1px solid #dddddd;
+}
+
+.table-bordered caption + thead tr:first-child th,
+.table-bordered caption + tbody tr:first-child th,
+.table-bordered caption + tbody tr:first-child td,
+.table-bordered colgroup + thead tr:first-child th,
+.table-bordered colgroup + tbody tr:first-child th,
+.table-bordered colgroup + tbody tr:first-child td,
+.table-bordered thead:first-child tr:first-child th,
+.table-bordered tbody:first-child tr:first-child th,
+.table-bordered tbody:first-child tr:first-child td {
+ border-top: 0;
+}
+
+.table-bordered thead:first-child tr:first-child > th:first-child,
+.table-bordered tbody:first-child tr:first-child > td:first-child,
+.table-bordered tbody:first-child tr:first-child > th:first-child {
+ -webkit-border-top-left-radius: 4px;
+ border-top-left-radius: 4px;
+ -moz-border-radius-topleft: 4px;
+}
+
+.table-bordered thead:first-child tr:first-child > th:last-child,
+.table-bordered tbody:first-child tr:first-child > td:last-child,
+.table-bordered tbody:first-child tr:first-child > th:last-child {
+ -webkit-border-top-right-radius: 4px;
+ border-top-right-radius: 4px;
+ -moz-border-radius-topright: 4px;
+}
+
+.table-bordered thead:last-child tr:last-child > th:first-child,
+.table-bordered tbody:last-child tr:last-child > td:first-child,
+.table-bordered tbody:last-child tr:last-child > th:first-child,
+.table-bordered tfoot:last-child tr:last-child > td:first-child,
+.table-bordered tfoot:last-child tr:last-child > th:first-child {
+ -webkit-border-bottom-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+ -moz-border-radius-bottomleft: 4px;
+}
+
+.table-bordered thead:last-child tr:last-child > th:last-child,
+.table-bordered tbody:last-child tr:last-child > td:last-child,
+.table-bordered tbody:last-child tr:last-child > th:last-child,
+.table-bordered tfoot:last-child tr:last-child > td:last-child,
+.table-bordered tfoot:last-child tr:last-child > th:last-child {
+ -webkit-border-bottom-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ -moz-border-radius-bottomright: 4px;
+}
+
+.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {
+ -webkit-border-bottom-left-radius: 0;
+ border-bottom-left-radius: 0;
+ -moz-border-radius-bottomleft: 0;
+}
+
+.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {
+ -webkit-border-bottom-right-radius: 0;
+ border-bottom-right-radius: 0;
+ -moz-border-radius-bottomright: 0;
+}
+
+.table-bordered caption + thead tr:first-child th:first-child,
+.table-bordered caption + tbody tr:first-child td:first-child,
+.table-bordered colgroup + thead tr:first-child th:first-child,
+.table-bordered colgroup + tbody tr:first-child td:first-child {
+ -webkit-border-top-left-radius: 4px;
+ border-top-left-radius: 4px;
+ -moz-border-radius-topleft: 4px;
+}
+
+.table-bordered caption + thead tr:first-child th:last-child,
+.table-bordered caption + tbody tr:first-child td:last-child,
+.table-bordered colgroup + thead tr:first-child th:last-child,
+.table-bordered colgroup + tbody tr:first-child td:last-child {
+ -webkit-border-top-right-radius: 4px;
+ border-top-right-radius: 4px;
+ -moz-border-radius-topright: 4px;
+}
+
+.table-striped tbody > tr:nth-child(odd) > td,
+.table-striped tbody > tr:nth-child(odd) > th {
+ background-color: #f9f9f9;
+}
+
+.table-hover tbody tr:hover > td,
+.table-hover tbody tr:hover > th {
+ background-color: #f5f5f5;
+}
+
+table td[class*="span"],
+table th[class*="span"],
+.row-fluid table td[class*="span"],
+.row-fluid table th[class*="span"] {
+ display: table-cell;
+ float: none;
+ margin-left: 0;
+}
+
+.table td.span1,
+.table th.span1 {
+ float: none;
+ width: 44px;
+ margin-left: 0;
+}
+
+.table td.span2,
+.table th.span2 {
+ float: none;
+ width: 124px;
+ margin-left: 0;
+}
+
+.table td.span3,
+.table th.span3 {
+ float: none;
+ width: 204px;
+ margin-left: 0;
+}
+
+.table td.span4,
+.table th.span4 {
+ float: none;
+ width: 284px;
+ margin-left: 0;
+}
+
+.table td.span5,
+.table th.span5 {
+ float: none;
+ width: 364px;
+ margin-left: 0;
+}
+
+.table td.span6,
+.table th.span6 {
+ float: none;
+ width: 444px;
+ margin-left: 0;
+}
+
+.table td.span7,
+.table th.span7 {
+ float: none;
+ width: 524px;
+ margin-left: 0;
+}
+
+.table td.span8,
+.table th.span8 {
+ float: none;
+ width: 604px;
+ margin-left: 0;
+}
+
+.table td.span9,
+.table th.span9 {
+ float: none;
+ width: 684px;
+ margin-left: 0;
+}
+
+.table td.span10,
+.table th.span10 {
+ float: none;
+ width: 764px;
+ margin-left: 0;
+}
+
+.table td.span11,
+.table th.span11 {
+ float: none;
+ width: 844px;
+ margin-left: 0;
+}
+
+.table td.span12,
+.table th.span12 {
+ float: none;
+ width: 924px;
+ margin-left: 0;
+}
+
+.table tbody tr.success > td {
+ background-color: #dff0d8;
+}
+
+.table tbody tr.error > td {
+ background-color: #f2dede;
+}
+
+.table tbody tr.warning > td {
+ background-color: #fcf8e3;
+}
+
+.table tbody tr.info > td {
+ background-color: #d9edf7;
+}
+
+.table-hover tbody tr.success:hover > td {
+ background-color: #d0e9c6;
+}
+
+.table-hover tbody tr.error:hover > td {
+ background-color: #ebcccc;
+}
+
+.table-hover tbody tr.warning:hover > td {
+ background-color: #faf2cc;
+}
+
+.table-hover tbody tr.info:hover > td {
+ background-color: #c4e3f3;
+}
+
+[class^="icon-"],
+[class*=" icon-"] {
+ display: inline-block;
+ width: 14px;
+ height: 14px;
+ margin-top: 1px;
+ *margin-right: .3em;
+ line-height: 14px;
+ vertical-align: text-top;
+ background-image: url("../img/glyphicons-halflings.png");
+ background-position: 14px 14px;
+ background-repeat: no-repeat;
+}
+
+/* White icons with optional class, or on hover/focus/active states of certain elements */
+
+.icon-white,
+.nav-pills > .active > a > [class^="icon-"],
+.nav-pills > .active > a > [class*=" icon-"],
+.nav-list > .active > a > [class^="icon-"],
+.nav-list > .active > a > [class*=" icon-"],
+.navbar-inverse .nav > .active > a > [class^="icon-"],
+.navbar-inverse .nav > .active > a > [class*=" icon-"],
+.dropdown-menu > li > a:hover > [class^="icon-"],
+.dropdown-menu > li > a:focus > [class^="icon-"],
+.dropdown-menu > li > a:hover > [class*=" icon-"],
+.dropdown-menu > li > a:focus > [class*=" icon-"],
+.dropdown-menu > .active > a > [class^="icon-"],
+.dropdown-menu > .active > a > [class*=" icon-"],
+.dropdown-submenu:hover > a > [class^="icon-"],
+.dropdown-submenu:focus > a > [class^="icon-"],
+.dropdown-submenu:hover > a > [class*=" icon-"],
+.dropdown-submenu:focus > a > [class*=" icon-"] {
+ background-image: url("../img/glyphicons-halflings-white.png");
+}
+
+.icon-glass {
+ background-position: 0 0;
+}
+
+.icon-music {
+ background-position: -24px 0;
+}
+
+.icon-search {
+ background-position: -48px 0;
+}
+
+.icon-envelope {
+ background-position: -72px 0;
+}
+
+.icon-heart {
+ background-position: -96px 0;
+}
+
+.icon-star {
+ background-position: -120px 0;
+}
+
+.icon-star-empty {
+ background-position: -144px 0;
+}
+
+.icon-user {
+ background-position: -168px 0;
+}
+
+.icon-film {
+ background-position: -192px 0;
+}
+
+.icon-th-large {
+ background-position: -216px 0;
+}
+
+.icon-th {
+ background-position: -240px 0;
+}
+
+.icon-th-list {
+ background-position: -264px 0;
+}
+
+.icon-ok {
+ background-position: -288px 0;
+}
+
+.icon-remove {
+ background-position: -312px 0;
+}
+
+.icon-zoom-in {
+ background-position: -336px 0;
+}
+
+.icon-zoom-out {
+ background-position: -360px 0;
+}
+
+.icon-off {
+ background-position: -384px 0;
+}
+
+.icon-signal {
+ background-position: -408px 0;
+}
+
+.icon-cog {
+ background-position: -432px 0;
+}
+
+.icon-trash {
+ background-position: -456px 0;
+}
+
+.icon-home {
+ background-position: 0 -24px;
+}
+
+.icon-file {
+ background-position: -24px -24px;
+}
+
+.icon-time {
+ background-position: -48px -24px;
+}
+
+.icon-road {
+ background-position: -72px -24px;
+}
+
+.icon-download-alt {
+ background-position: -96px -24px;
+}
+
+.icon-download {
+ background-position: -120px -24px;
+}
+
+.icon-upload {
+ background-position: -144px -24px;
+}
+
+.icon-inbox {
+ background-position: -168px -24px;
+}
+
+.icon-play-circle {
+ background-position: -192px -24px;
+}
+
+.icon-repeat {
+ background-position: -216px -24px;
+}
+
+.icon-refresh {
+ background-position: -240px -24px;
+}
+
+.icon-list-alt {
+ background-position: -264px -24px;
+}
+
+.icon-lock {
+ background-position: -287px -24px;
+}
+
+.icon-flag {
+ background-position: -312px -24px;
+}
+
+.icon-headphones {
+ background-position: -336px -24px;
+}
+
+.icon-volume-off {
+ background-position: -360px -24px;
+}
+
+.icon-volume-down {
+ background-position: -384px -24px;
+}
+
+.icon-volume-up {
+ background-position: -408px -24px;
+}
+
+.icon-qrcode {
+ background-position: -432px -24px;
+}
+
+.icon-barcode {
+ background-position: -456px -24px;
+}
+
+.icon-tag {
+ background-position: 0 -48px;
+}
+
+.icon-tags {
+ background-position: -25px -48px;
+}
+
+.icon-book {
+ background-position: -48px -48px;
+}
+
+.icon-bookmark {
+ background-position: -72px -48px;
+}
+
+.icon-print {
+ background-position: -96px -48px;
+}
+
+.icon-camera {
+ background-position: -120px -48px;
+}
+
+.icon-font {
+ background-position: -144px -48px;
+}
+
+.icon-bold {
+ background-position: -167px -48px;
+}
+
+.icon-italic {
+ background-position: -192px -48px;
+}
+
+.icon-text-height {
+ background-position: -216px -48px;
+}
+
+.icon-text-width {
+ background-position: -240px -48px;
+}
+
+.icon-align-left {
+ background-position: -264px -48px;
+}
+
+.icon-align-center {
+ background-position: -288px -48px;
+}
+
+.icon-align-right {
+ background-position: -312px -48px;
+}
+
+.icon-align-justify {
+ background-position: -336px -48px;
+}
+
+.icon-list {
+ background-position: -360px -48px;
+}
+
+.icon-indent-left {
+ background-position: -384px -48px;
+}
+
+.icon-indent-right {
+ background-position: -408px -48px;
+}
+
+.icon-facetime-video {
+ background-position: -432px -48px;
+}
+
+.icon-picture {
+ background-position: -456px -48px;
+}
+
+.icon-pencil {
+ background-position: 0 -72px;
+}
+
+.icon-map-marker {
+ background-position: -24px -72px;
+}
+
+.icon-adjust {
+ background-position: -48px -72px;
+}
+
+.icon-tint {
+ background-position: -72px -72px;
+}
+
+.icon-edit {
+ background-position: -96px -72px;
+}
+
+.icon-share {
+ background-position: -120px -72px;
+}
+
+.icon-check {
+ background-position: -144px -72px;
+}
+
+.icon-move {
+ background-position: -168px -72px;
+}
+
+.icon-step-backward {
+ background-position: -192px -72px;
+}
+
+.icon-fast-backward {
+ background-position: -216px -72px;
+}
+
+.icon-backward {
+ background-position: -240px -72px;
+}
+
+.icon-play {
+ background-position: -264px -72px;
+}
+
+.icon-pause {
+ background-position: -288px -72px;
+}
+
+.icon-stop {
+ background-position: -312px -72px;
+}
+
+.icon-forward {
+ background-position: -336px -72px;
+}
+
+.icon-fast-forward {
+ background-position: -360px -72px;
+}
+
+.icon-step-forward {
+ background-position: -384px -72px;
+}
+
+.icon-eject {
+ background-position: -408px -72px;
+}
+
+.icon-chevron-left {
+ background-position: -432px -72px;
+}
+
+.icon-chevron-right {
+ background-position: -456px -72px;
+}
+
+.icon-plus-sign {
+ background-position: 0 -96px;
+}
+
+.icon-minus-sign {
+ background-position: -24px -96px;
+}
+
+.icon-remove-sign {
+ background-position: -48px -96px;
+}
+
+.icon-ok-sign {
+ background-position: -72px -96px;
+}
+
+.icon-question-sign {
+ background-position: -96px -96px;
+}
+
+.icon-info-sign {
+ background-position: -120px -96px;
+}
+
+.icon-screenshot {
+ background-position: -144px -96px;
+}
+
+.icon-remove-circle {
+ background-position: -168px -96px;
+}
+
+.icon-ok-circle {
+ background-position: -192px -96px;
+}
+
+.icon-ban-circle {
+ background-position: -216px -96px;
+}
+
+.icon-arrow-left {
+ background-position: -240px -96px;
+}
+
+.icon-arrow-right {
+ background-position: -264px -96px;
+}
+
+.icon-arrow-up {
+ background-position: -289px -96px;
+}
+
+.icon-arrow-down {
+ background-position: -312px -96px;
+}
+
+.icon-share-alt {
+ background-position: -336px -96px;
+}
+
+.icon-resize-full {
+ background-position: -360px -96px;
+}
+
+.icon-resize-small {
+ background-position: -384px -96px;
+}
+
+.icon-plus {
+ background-position: -408px -96px;
+}
+
+.icon-minus {
+ background-position: -433px -96px;
+}
+
+.icon-asterisk {
+ background-position: -456px -96px;
+}
+
+.icon-exclamation-sign {
+ background-position: 0 -120px;
+}
+
+.icon-gift {
+ background-position: -24px -120px;
+}
+
+.icon-leaf {
+ background-position: -48px -120px;
+}
+
+.icon-fire {
+ background-position: -72px -120px;
+}
+
+.icon-eye-open {
+ background-position: -96px -120px;
+}
+
+.icon-eye-close {
+ background-position: -120px -120px;
+}
+
+.icon-warning-sign {
+ background-position: -144px -120px;
+}
+
+.icon-plane {
+ background-position: -168px -120px;
+}
+
+.icon-calendar {
+ background-position: -192px -120px;
+}
+
+.icon-random {
+ width: 16px;
+ background-position: -216px -120px;
+}
+
+.icon-comment {
+ background-position: -240px -120px;
+}
+
+.icon-magnet {
+ background-position: -264px -120px;
+}
+
+.icon-chevron-up {
+ background-position: -288px -120px;
+}
+
+.icon-chevron-down {
+ background-position: -313px -119px;
+}
+
+.icon-retweet {
+ background-position: -336px -120px;
+}
+
+.icon-shopping-cart {
+ background-position: -360px -120px;
+}
+
+.icon-folder-close {
+ width: 16px;
+ background-position: -384px -120px;
+}
+
+.icon-folder-open {
+ width: 16px;
+ background-position: -408px -120px;
+}
+
+.icon-resize-vertical {
+ background-position: -432px -119px;
+}
+
+.icon-resize-horizontal {
+ background-position: -456px -118px;
+}
+
+.icon-hdd {
+ background-position: 0 -144px;
+}
+
+.icon-bullhorn {
+ background-position: -24px -144px;
+}
+
+.icon-bell {
+ background-position: -48px -144px;
+}
+
+.icon-certificate {
+ background-position: -72px -144px;
+}
+
+.icon-thumbs-up {
+ background-position: -96px -144px;
+}
+
+.icon-thumbs-down {
+ background-position: -120px -144px;
+}
+
+.icon-hand-right {
+ background-position: -144px -144px;
+}
+
+.icon-hand-left {
+ background-position: -168px -144px;
+}
+
+.icon-hand-up {
+ background-position: -192px -144px;
+}
+
+.icon-hand-down {
+ background-position: -216px -144px;
+}
+
+.icon-circle-arrow-right {
+ background-position: -240px -144px;
+}
+
+.icon-circle-arrow-left {
+ background-position: -264px -144px;
+}
+
+.icon-circle-arrow-up {
+ background-position: -288px -144px;
+}
+
+.icon-circle-arrow-down {
+ background-position: -312px -144px;
+}
+
+.icon-globe {
+ background-position: -336px -144px;
+}
+
+.icon-wrench {
+ background-position: -360px -144px;
+}
+
+.icon-tasks {
+ background-position: -384px -144px;
+}
+
+.icon-filter {
+ background-position: -408px -144px;
+}
+
+.icon-briefcase {
+ background-position: -432px -144px;
+}
+
+.icon-fullscreen {
+ background-position: -456px -144px;
+}
+
+.dropup,
+.dropdown {
+ position: relative;
+}
+
+.dropdown-toggle {
+ *margin-bottom: -3px;
+}
+
+.dropdown-toggle:active,
+.open .dropdown-toggle {
+ outline: 0;
+}
+
+.caret {
+ display: inline-block;
+ width: 0;
+ height: 0;
+ vertical-align: top;
+ border-top: 4px solid #000000;
+ border-right: 4px solid transparent;
+ border-left: 4px solid transparent;
+ content: "";
+}
+
+.dropdown .caret {
+ margin-top: 8px;
+ margin-left: 2px;
+}
+
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 160px;
+ padding: 5px 0;
+ margin: 2px 0 0;
+ list-style: none;
+ background-color: #ffffff;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ *border-right-width: 2px;
+ *border-bottom-width: 2px;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding;
+ background-clip: padding-box;
+}
+
+.dropdown-menu.pull-right {
+ right: 0;
+ left: auto;
+}
+
+.dropdown-menu .divider {
+ *width: 100%;
+ height: 1px;
+ margin: 9px 1px;
+ *margin: -5px 0 5px;
+ overflow: hidden;
+ background-color: #e5e5e5;
+ border-bottom: 1px solid #ffffff;
+}
+
+.dropdown-menu > li > a {
+ display: block;
+ padding: 3px 20px;
+ clear: both;
+ font-weight: normal;
+ line-height: 20px;
+ color: #333333;
+ white-space: nowrap;
+}
+
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus,
+.dropdown-submenu:hover > a,
+.dropdown-submenu:focus > a {
+ color: #ffffff;
+ text-decoration: none;
+ background-color: #0081c2;
+ background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
+ background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
+ background-image: -o-linear-gradient(top, #0088cc, #0077b3);
+ background-image: linear-gradient(to bottom, #0088cc, #0077b3);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
+}
+
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+ color: #ffffff;
+ text-decoration: none;
+ background-color: #0081c2;
+ background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
+ background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
+ background-image: -o-linear-gradient(top, #0088cc, #0077b3);
+ background-image: linear-gradient(to bottom, #0088cc, #0077b3);
+ background-repeat: repeat-x;
+ outline: 0;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
+}
+
+.dropdown-menu > .disabled > a,
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+ color: #999999;
+}
+
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+ text-decoration: none;
+ cursor: default;
+ background-color: transparent;
+ background-image: none;
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.open {
+ *z-index: 1000;
+}
+
+.open > .dropdown-menu {
+ display: block;
+}
+
+.pull-right > .dropdown-menu {
+ right: 0;
+ left: auto;
+}
+
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+ border-top: 0;
+ border-bottom: 4px solid #000000;
+ content: "";
+}
+
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+ top: auto;
+ bottom: 100%;
+ margin-bottom: 1px;
+}
+
+.dropdown-submenu {
+ position: relative;
+}
+
+.dropdown-submenu > .dropdown-menu {
+ top: 0;
+ left: 100%;
+ margin-top: -6px;
+ margin-left: -1px;
+ -webkit-border-radius: 0 6px 6px 6px;
+ -moz-border-radius: 0 6px 6px 6px;
+ border-radius: 0 6px 6px 6px;
+}
+
+.dropdown-submenu:hover > .dropdown-menu {
+ display: block;
+}
+
+.dropup .dropdown-submenu > .dropdown-menu {
+ top: auto;
+ bottom: 0;
+ margin-top: 0;
+ margin-bottom: -2px;
+ -webkit-border-radius: 5px 5px 5px 0;
+ -moz-border-radius: 5px 5px 5px 0;
+ border-radius: 5px 5px 5px 0;
+}
+
+.dropdown-submenu > a:after {
+ display: block;
+ float: right;
+ width: 0;
+ height: 0;
+ margin-top: 5px;
+ margin-right: -10px;
+ border-color: transparent;
+ border-left-color: #cccccc;
+ border-style: solid;
+ border-width: 5px 0 5px 5px;
+ content: " ";
+}
+
+.dropdown-submenu:hover > a:after {
+ border-left-color: #ffffff;
+}
+
+.dropdown-submenu.pull-left {
+ float: none;
+}
+
+.dropdown-submenu.pull-left > .dropdown-menu {
+ left: -100%;
+ margin-left: 10px;
+ -webkit-border-radius: 6px 0 6px 6px;
+ -moz-border-radius: 6px 0 6px 6px;
+ border-radius: 6px 0 6px 6px;
+}
+
+.dropdown .dropdown-menu .nav-header {
+ padding-right: 20px;
+ padding-left: 20px;
+}
+
+.typeahead {
+ z-index: 1051;
+ margin-top: 2px;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.well {
+ min-height: 20px;
+ padding: 19px;
+ margin-bottom: 20px;
+ background-color: #f5f5f5;
+ border: 1px solid #e3e3e3;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+}
+
+.well blockquote {
+ border-color: #ddd;
+ border-color: rgba(0, 0, 0, 0.15);
+}
+
+.well-large {
+ padding: 24px;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+}
+
+.well-small {
+ padding: 9px;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+
+.fade {
+ opacity: 0;
+ -webkit-transition: opacity 0.15s linear;
+ -moz-transition: opacity 0.15s linear;
+ -o-transition: opacity 0.15s linear;
+ transition: opacity 0.15s linear;
+}
+
+.fade.in {
+ opacity: 1;
+}
+
+.collapse {
+ position: relative;
+ height: 0;
+ overflow: hidden;
+ -webkit-transition: height 0.35s ease;
+ -moz-transition: height 0.35s ease;
+ -o-transition: height 0.35s ease;
+ transition: height 0.35s ease;
+}
+
+.collapse.in {
+ height: auto;
+}
+
+.close {
+ float: right;
+ font-size: 20px;
+ font-weight: bold;
+ line-height: 20px;
+ color: #000000;
+ text-shadow: 0 1px 0 #ffffff;
+ opacity: 0.2;
+ filter: alpha(opacity=20);
+}
+
+.close:hover,
+.close:focus {
+ color: #000000;
+ text-decoration: none;
+ cursor: pointer;
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+}
+
+button.close {
+ padding: 0;
+ cursor: pointer;
+ background: transparent;
+ border: 0;
+ -webkit-appearance: none;
+}
+
+.btn {
+ display: inline-block;
+ *display: inline;
+ padding: 4px 12px;
+ margin-bottom: 0;
+ *margin-left: .3em;
+ font-size: 14px;
+ line-height: 20px;
+ color: #333333;
+ text-align: center;
+ text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
+ vertical-align: middle;
+ cursor: pointer;
+ background-color: #f5f5f5;
+ *background-color: #e6e6e6;
+ background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
+ background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
+ background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
+ background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
+ background-repeat: repeat-x;
+ border: 1px solid #cccccc;
+ *border: 0;
+ border-color: #e6e6e6 #e6e6e6 #bfbfbf;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ border-bottom-color: #b3b3b3;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+ *zoom: 1;
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn:hover,
+.btn:focus,
+.btn:active,
+.btn.active,
+.btn.disabled,
+.btn[disabled] {
+ color: #333333;
+ background-color: #e6e6e6;
+ *background-color: #d9d9d9;
+}
+
+.btn:active,
+.btn.active {
+ background-color: #cccccc \9;
+}
+
+.btn:first-child {
+ *margin-left: 0;
+}
+
+.btn:hover,
+.btn:focus {
+ color: #333333;
+ text-decoration: none;
+ background-position: 0 -15px;
+ -webkit-transition: background-position 0.1s linear;
+ -moz-transition: background-position 0.1s linear;
+ -o-transition: background-position 0.1s linear;
+ transition: background-position 0.1s linear;
+}
+
+.btn:focus {
+ outline: thin dotted #333;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+
+.btn.active,
+.btn:active {
+ background-image: none;
+ outline: 0;
+ -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn.disabled,
+.btn[disabled] {
+ cursor: default;
+ background-image: none;
+ opacity: 0.65;
+ filter: alpha(opacity=65);
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ box-shadow: none;
+}
+
+.btn-large {
+ padding: 11px 19px;
+ font-size: 17.5px;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+}
+
+.btn-large [class^="icon-"],
+.btn-large [class*=" icon-"] {
+ margin-top: 4px;
+}
+
+.btn-small {
+ padding: 2px 10px;
+ font-size: 11.9px;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+
+.btn-small [class^="icon-"],
+.btn-small [class*=" icon-"] {
+ margin-top: 0;
+}
+
+.btn-mini [class^="icon-"],
+.btn-mini [class*=" icon-"] {
+ margin-top: -1px;
+}
+
+.btn-mini {
+ padding: 0 6px;
+ font-size: 10.5px;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+
+.btn-block {
+ display: block;
+ width: 100%;
+ padding-right: 0;
+ padding-left: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+.btn-block + .btn-block {
+ margin-top: 5px;
+}
+
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+ width: 100%;
+}
+
+.btn-primary.active,
+.btn-warning.active,
+.btn-danger.active,
+.btn-success.active,
+.btn-info.active,
+.btn-inverse.active {
+ color: rgba(255, 255, 255, 0.75);
+}
+
+.btn-primary {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #006dcc;
+ *background-color: #0044cc;
+ background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
+ background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
+ background-image: -o-linear-gradient(top, #0088cc, #0044cc);
+ background-image: linear-gradient(to bottom, #0088cc, #0044cc);
+ background-repeat: repeat-x;
+ border-color: #0044cc #0044cc #002a80;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-primary:hover,
+.btn-primary:focus,
+.btn-primary:active,
+.btn-primary.active,
+.btn-primary.disabled,
+.btn-primary[disabled] {
+ color: #ffffff;
+ background-color: #0044cc;
+ *background-color: #003bb3;
+}
+
+.btn-primary:active,
+.btn-primary.active {
+ background-color: #003399 \9;
+}
+
+.btn-warning {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #faa732;
+ *background-color: #f89406;
+ background-image: -moz-linear-gradient(top, #fbb450, #f89406);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
+ background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
+ background-image: -o-linear-gradient(top, #fbb450, #f89406);
+ background-image: linear-gradient(to bottom, #fbb450, #f89406);
+ background-repeat: repeat-x;
+ border-color: #f89406 #f89406 #ad6704;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-warning:hover,
+.btn-warning:focus,
+.btn-warning:active,
+.btn-warning.active,
+.btn-warning.disabled,
+.btn-warning[disabled] {
+ color: #ffffff;
+ background-color: #f89406;
+ *background-color: #df8505;
+}
+
+.btn-warning:active,
+.btn-warning.active {
+ background-color: #c67605 \9;
+}
+
+.btn-danger {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #da4f49;
+ *background-color: #bd362f;
+ background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));
+ background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);
+ background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);
+ background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);
+ background-repeat: repeat-x;
+ border-color: #bd362f #bd362f #802420;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-danger:hover,
+.btn-danger:focus,
+.btn-danger:active,
+.btn-danger.active,
+.btn-danger.disabled,
+.btn-danger[disabled] {
+ color: #ffffff;
+ background-color: #bd362f;
+ *background-color: #a9302a;
+}
+
+.btn-danger:active,
+.btn-danger.active {
+ background-color: #942a25 \9;
+}
+
+.btn-success {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #5bb75b;
+ *background-color: #51a351;
+ background-image: -moz-linear-gradient(top, #62c462, #51a351);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));
+ background-image: -webkit-linear-gradient(top, #62c462, #51a351);
+ background-image: -o-linear-gradient(top, #62c462, #51a351);
+ background-image: linear-gradient(to bottom, #62c462, #51a351);
+ background-repeat: repeat-x;
+ border-color: #51a351 #51a351 #387038;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-success:hover,
+.btn-success:focus,
+.btn-success:active,
+.btn-success.active,
+.btn-success.disabled,
+.btn-success[disabled] {
+ color: #ffffff;
+ background-color: #51a351;
+ *background-color: #499249;
+}
+
+.btn-success:active,
+.btn-success.active {
+ background-color: #408140 \9;
+}
+
+.btn-info {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #49afcd;
+ *background-color: #2f96b4;
+ background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));
+ background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);
+ background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);
+ background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);
+ background-repeat: repeat-x;
+ border-color: #2f96b4 #2f96b4 #1f6377;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-info:hover,
+.btn-info:focus,
+.btn-info:active,
+.btn-info.active,
+.btn-info.disabled,
+.btn-info[disabled] {
+ color: #ffffff;
+ background-color: #2f96b4;
+ *background-color: #2a85a0;
+}
+
+.btn-info:active,
+.btn-info.active {
+ background-color: #24748c \9;
+}
+
+.btn-inverse {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #363636;
+ *background-color: #222222;
+ background-image: -moz-linear-gradient(top, #444444, #222222);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));
+ background-image: -webkit-linear-gradient(top, #444444, #222222);
+ background-image: -o-linear-gradient(top, #444444, #222222);
+ background-image: linear-gradient(to bottom, #444444, #222222);
+ background-repeat: repeat-x;
+ border-color: #222222 #222222 #000000;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.btn-inverse:hover,
+.btn-inverse:focus,
+.btn-inverse:active,
+.btn-inverse.active,
+.btn-inverse.disabled,
+.btn-inverse[disabled] {
+ color: #ffffff;
+ background-color: #222222;
+ *background-color: #151515;
+}
+
+.btn-inverse:active,
+.btn-inverse.active {
+ background-color: #080808 \9;
+}
+
+button.btn,
+input[type="submit"].btn {
+ *padding-top: 3px;
+ *padding-bottom: 3px;
+}
+
+button.btn::-moz-focus-inner,
+input[type="submit"].btn::-moz-focus-inner {
+ padding: 0;
+ border: 0;
+}
+
+button.btn.btn-large,
+input[type="submit"].btn.btn-large {
+ *padding-top: 7px;
+ *padding-bottom: 7px;
+}
+
+button.btn.btn-small,
+input[type="submit"].btn.btn-small {
+ *padding-top: 3px;
+ *padding-bottom: 3px;
+}
+
+button.btn.btn-mini,
+input[type="submit"].btn.btn-mini {
+ *padding-top: 1px;
+ *padding-bottom: 1px;
+}
+
+.btn-link,
+.btn-link:active,
+.btn-link[disabled] {
+ background-color: transparent;
+ background-image: none;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ box-shadow: none;
+}
+
+.btn-link {
+ color: #0088cc;
+ cursor: pointer;
+ border-color: transparent;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.btn-link:hover,
+.btn-link:focus {
+ color: #005580;
+ text-decoration: underline;
+ background-color: transparent;
+}
+
+.btn-link[disabled]:hover,
+.btn-link[disabled]:focus {
+ color: #333333;
+ text-decoration: none;
+}
+
+.btn-group {
+ position: relative;
+ display: inline-block;
+ *display: inline;
+ *margin-left: .3em;
+ font-size: 0;
+ white-space: nowrap;
+ vertical-align: middle;
+ *zoom: 1;
+}
+
+.btn-group:first-child {
+ *margin-left: 0;
+}
+
+.btn-group + .btn-group {
+ margin-left: 5px;
+}
+
+.btn-toolbar {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ font-size: 0;
+}
+
+.btn-toolbar > .btn + .btn,
+.btn-toolbar > .btn-group + .btn,
+.btn-toolbar > .btn + .btn-group {
+ margin-left: 5px;
+}
+
+.btn-group > .btn {
+ position: relative;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.btn-group > .btn + .btn {
+ margin-left: -1px;
+}
+
+.btn-group > .btn,
+.btn-group > .dropdown-menu,
+.btn-group > .popover {
+ font-size: 14px;
+}
+
+.btn-group > .btn-mini {
+ font-size: 10.5px;
+}
+
+.btn-group > .btn-small {
+ font-size: 11.9px;
+}
+
+.btn-group > .btn-large {
+ font-size: 17.5px;
+}
+
+.btn-group > .btn:first-child {
+ margin-left: 0;
+ -webkit-border-bottom-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+ -webkit-border-top-left-radius: 4px;
+ border-top-left-radius: 4px;
+ -moz-border-radius-bottomleft: 4px;
+ -moz-border-radius-topleft: 4px;
+}
+
+.btn-group > .btn:last-child,
+.btn-group > .dropdown-toggle {
+ -webkit-border-top-right-radius: 4px;
+ border-top-right-radius: 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ -moz-border-radius-topright: 4px;
+ -moz-border-radius-bottomright: 4px;
+}
+
+.btn-group > .btn.large:first-child {
+ margin-left: 0;
+ -webkit-border-bottom-left-radius: 6px;
+ border-bottom-left-radius: 6px;
+ -webkit-border-top-left-radius: 6px;
+ border-top-left-radius: 6px;
+ -moz-border-radius-bottomleft: 6px;
+ -moz-border-radius-topleft: 6px;
+}
+
+.btn-group > .btn.large:last-child,
+.btn-group > .large.dropdown-toggle {
+ -webkit-border-top-right-radius: 6px;
+ border-top-right-radius: 6px;
+ -webkit-border-bottom-right-radius: 6px;
+ border-bottom-right-radius: 6px;
+ -moz-border-radius-topright: 6px;
+ -moz-border-radius-bottomright: 6px;
+}
+
+.btn-group > .btn:hover,
+.btn-group > .btn:focus,
+.btn-group > .btn:active,
+.btn-group > .btn.active {
+ z-index: 2;
+}
+
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+ outline: 0;
+}
+
+.btn-group > .btn + .dropdown-toggle {
+ *padding-top: 5px;
+ padding-right: 8px;
+ *padding-bottom: 5px;
+ padding-left: 8px;
+ -webkit-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn-group > .btn-mini + .dropdown-toggle {
+ *padding-top: 2px;
+ padding-right: 5px;
+ *padding-bottom: 2px;
+ padding-left: 5px;
+}
+
+.btn-group > .btn-small + .dropdown-toggle {
+ *padding-top: 5px;
+ *padding-bottom: 4px;
+}
+
+.btn-group > .btn-large + .dropdown-toggle {
+ *padding-top: 7px;
+ padding-right: 12px;
+ *padding-bottom: 7px;
+ padding-left: 12px;
+}
+
+.btn-group.open .dropdown-toggle {
+ background-image: none;
+ -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.btn-group.open .btn.dropdown-toggle {
+ background-color: #e6e6e6;
+}
+
+.btn-group.open .btn-primary.dropdown-toggle {
+ background-color: #0044cc;
+}
+
+.btn-group.open .btn-warning.dropdown-toggle {
+ background-color: #f89406;
+}
+
+.btn-group.open .btn-danger.dropdown-toggle {
+ background-color: #bd362f;
+}
+
+.btn-group.open .btn-success.dropdown-toggle {
+ background-color: #51a351;
+}
+
+.btn-group.open .btn-info.dropdown-toggle {
+ background-color: #2f96b4;
+}
+
+.btn-group.open .btn-inverse.dropdown-toggle {
+ background-color: #222222;
+}
+
+.btn .caret {
+ margin-top: 8px;
+ margin-left: 0;
+}
+
+.btn-large .caret {
+ margin-top: 6px;
+}
+
+.btn-large .caret {
+ border-top-width: 5px;
+ border-right-width: 5px;
+ border-left-width: 5px;
+}
+
+.btn-mini .caret,
+.btn-small .caret {
+ margin-top: 8px;
+}
+
+.dropup .btn-large .caret {
+ border-bottom-width: 5px;
+}
+
+.btn-primary .caret,
+.btn-warning .caret,
+.btn-danger .caret,
+.btn-info .caret,
+.btn-success .caret,
+.btn-inverse .caret {
+ border-top-color: #ffffff;
+ border-bottom-color: #ffffff;
+}
+
+.btn-group-vertical {
+ display: inline-block;
+ *display: inline;
+ /* IE7 inline-block hack */
+
+ *zoom: 1;
+}
+
+.btn-group-vertical > .btn {
+ display: block;
+ float: none;
+ max-width: 100%;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.btn-group-vertical > .btn + .btn {
+ margin-top: -1px;
+ margin-left: 0;
+}
+
+.btn-group-vertical > .btn:first-child {
+ -webkit-border-radius: 4px 4px 0 0;
+ -moz-border-radius: 4px 4px 0 0;
+ border-radius: 4px 4px 0 0;
+}
+
+.btn-group-vertical > .btn:last-child {
+ -webkit-border-radius: 0 0 4px 4px;
+ -moz-border-radius: 0 0 4px 4px;
+ border-radius: 0 0 4px 4px;
+}
+
+.btn-group-vertical > .btn-large:first-child {
+ -webkit-border-radius: 6px 6px 0 0;
+ -moz-border-radius: 6px 6px 0 0;
+ border-radius: 6px 6px 0 0;
+}
+
+.btn-group-vertical > .btn-large:last-child {
+ -webkit-border-radius: 0 0 6px 6px;
+ -moz-border-radius: 0 0 6px 6px;
+ border-radius: 0 0 6px 6px;
+}
+
+.alert {
+ padding: 8px 35px 8px 14px;
+ margin-bottom: 20px;
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+ background-color: #fcf8e3;
+ border: 1px solid #fbeed5;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.alert,
+.alert h4 {
+ color: #c09853;
+}
+
+.alert h4 {
+ margin: 0;
+}
+
+.alert .close {
+ position: relative;
+ top: -2px;
+ right: -21px;
+ line-height: 20px;
+}
+
+.alert-success {
+ color: #468847;
+ background-color: #dff0d8;
+ border-color: #d6e9c6;
+}
+
+.alert-success h4 {
+ color: #468847;
+}
+
+.alert-danger,
+.alert-error {
+ color: #b94a48;
+ background-color: #f2dede;
+ border-color: #eed3d7;
+}
+
+.alert-danger h4,
+.alert-error h4 {
+ color: #b94a48;
+}
+
+.alert-info {
+ color: #3a87ad;
+ background-color: #d9edf7;
+ border-color: #bce8f1;
+}
+
+.alert-info h4 {
+ color: #3a87ad;
+}
+
+.alert-block {
+ padding-top: 14px;
+ padding-bottom: 14px;
+}
+
+.alert-block > p,
+.alert-block > ul {
+ margin-bottom: 0;
+}
+
+.alert-block p + p {
+ margin-top: 5px;
+}
+
+.nav {
+ margin-bottom: 20px;
+ margin-left: 0;
+ list-style: none;
+}
+
+.nav > li > a {
+ display: block;
+}
+
+.nav > li > a:hover,
+.nav > li > a:focus {
+ text-decoration: none;
+ background-color: #eeeeee;
+}
+
+.nav > li > a > img {
+ max-width: none;
+}
+
+.nav > .pull-right {
+ float: right;
+}
+
+.nav-header {
+ display: block;
+ padding: 3px 15px;
+ font-size: 11px;
+ font-weight: bold;
+ line-height: 20px;
+ color: #999999;
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+ text-transform: uppercase;
+}
+
+.nav li + .nav-header {
+ margin-top: 9px;
+}
+
+.nav-list {
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-bottom: 0;
+}
+
+.nav-list > li > a,
+.nav-list .nav-header {
+ margin-right: -15px;
+ margin-left: -15px;
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+}
+
+.nav-list > li > a {
+ padding: 3px 15px;
+}
+
+.nav-list > .active > a,
+.nav-list > .active > a:hover,
+.nav-list > .active > a:focus {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
+ background-color: #0088cc;
+}
+
+.nav-list [class^="icon-"],
+.nav-list [class*=" icon-"] {
+ margin-right: 2px;
+}
+
+.nav-list .divider {
+ *width: 100%;
+ height: 1px;
+ margin: 9px 1px;
+ *margin: -5px 0 5px;
+ overflow: hidden;
+ background-color: #e5e5e5;
+ border-bottom: 1px solid #ffffff;
+}
+
+.nav-tabs,
+.nav-pills {
+ *zoom: 1;
+}
+
+.nav-tabs:before,
+.nav-pills:before,
+.nav-tabs:after,
+.nav-pills:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.nav-tabs:after,
+.nav-pills:after {
+ clear: both;
+}
+
+.nav-tabs > li,
+.nav-pills > li {
+ float: left;
+}
+
+.nav-tabs > li > a,
+.nav-pills > li > a {
+ padding-right: 12px;
+ padding-left: 12px;
+ margin-right: 2px;
+ line-height: 14px;
+}
+
+.nav-tabs {
+ border-bottom: 1px solid #ddd;
+}
+
+.nav-tabs > li {
+ margin-bottom: -1px;
+}
+
+.nav-tabs > li > a {
+ padding-top: 8px;
+ padding-bottom: 8px;
+ line-height: 20px;
+ border: 1px solid transparent;
+ -webkit-border-radius: 4px 4px 0 0;
+ -moz-border-radius: 4px 4px 0 0;
+ border-radius: 4px 4px 0 0;
+}
+
+.nav-tabs > li > a:hover,
+.nav-tabs > li > a:focus {
+ border-color: #eeeeee #eeeeee #dddddd;
+}
+
+.nav-tabs > .active > a,
+.nav-tabs > .active > a:hover,
+.nav-tabs > .active > a:focus {
+ color: #555555;
+ cursor: default;
+ background-color: #ffffff;
+ border: 1px solid #ddd;
+ border-bottom-color: transparent;
+}
+
+.nav-pills > li > a {
+ padding-top: 8px;
+ padding-bottom: 8px;
+ margin-top: 2px;
+ margin-bottom: 2px;
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+}
+
+.nav-pills > .active > a,
+.nav-pills > .active > a:hover,
+.nav-pills > .active > a:focus {
+ color: #ffffff;
+ background-color: #0088cc;
+}
+
+.nav-stacked > li {
+ float: none;
+}
+
+.nav-stacked > li > a {
+ margin-right: 0;
+}
+
+.nav-tabs.nav-stacked {
+ border-bottom: 0;
+}
+
+.nav-tabs.nav-stacked > li > a {
+ border: 1px solid #ddd;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.nav-tabs.nav-stacked > li:first-child > a {
+ -webkit-border-top-right-radius: 4px;
+ border-top-right-radius: 4px;
+ -webkit-border-top-left-radius: 4px;
+ border-top-left-radius: 4px;
+ -moz-border-radius-topright: 4px;
+ -moz-border-radius-topleft: 4px;
+}
+
+.nav-tabs.nav-stacked > li:last-child > a {
+ -webkit-border-bottom-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ -webkit-border-bottom-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+ -moz-border-radius-bottomright: 4px;
+ -moz-border-radius-bottomleft: 4px;
+}
+
+.nav-tabs.nav-stacked > li > a:hover,
+.nav-tabs.nav-stacked > li > a:focus {
+ z-index: 2;
+ border-color: #ddd;
+}
+
+.nav-pills.nav-stacked > li > a {
+ margin-bottom: 3px;
+}
+
+.nav-pills.nav-stacked > li:last-child > a {
+ margin-bottom: 1px;
+}
+
+.nav-tabs .dropdown-menu {
+ -webkit-border-radius: 0 0 6px 6px;
+ -moz-border-radius: 0 0 6px 6px;
+ border-radius: 0 0 6px 6px;
+}
+
+.nav-pills .dropdown-menu {
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+}
+
+.nav .dropdown-toggle .caret {
+ margin-top: 6px;
+ border-top-color: #0088cc;
+ border-bottom-color: #0088cc;
+}
+
+.nav .dropdown-toggle:hover .caret,
+.nav .dropdown-toggle:focus .caret {
+ border-top-color: #005580;
+ border-bottom-color: #005580;
+}
+
+/* move down carets for tabs */
+
+.nav-tabs .dropdown-toggle .caret {
+ margin-top: 8px;
+}
+
+.nav .active .dropdown-toggle .caret {
+ border-top-color: #fff;
+ border-bottom-color: #fff;
+}
+
+.nav-tabs .active .dropdown-toggle .caret {
+ border-top-color: #555555;
+ border-bottom-color: #555555;
+}
+
+.nav > .dropdown.active > a:hover,
+.nav > .dropdown.active > a:focus {
+ cursor: pointer;
+}
+
+.nav-tabs .open .dropdown-toggle,
+.nav-pills .open .dropdown-toggle,
+.nav > li.dropdown.open.active > a:hover,
+.nav > li.dropdown.open.active > a:focus {
+ color: #ffffff;
+ background-color: #999999;
+ border-color: #999999;
+}
+
+.nav li.dropdown.open .caret,
+.nav li.dropdown.open.active .caret,
+.nav li.dropdown.open a:hover .caret,
+.nav li.dropdown.open a:focus .caret {
+ border-top-color: #ffffff;
+ border-bottom-color: #ffffff;
+ opacity: 1;
+ filter: alpha(opacity=100);
+}
+
+.tabs-stacked .open > a:hover,
+.tabs-stacked .open > a:focus {
+ border-color: #999999;
+}
+
+.tabbable {
+ *zoom: 1;
+}
+
+.tabbable:before,
+.tabbable:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.tabbable:after {
+ clear: both;
+}
+
+.tab-content {
+ overflow: auto;
+}
+
+.tabs-below > .nav-tabs,
+.tabs-right > .nav-tabs,
+.tabs-left > .nav-tabs {
+ border-bottom: 0;
+}
+
+.tab-content > .tab-pane,
+.pill-content > .pill-pane {
+ display: none;
+}
+
+.tab-content > .active,
+.pill-content > .active {
+ display: block;
+}
+
+.tabs-below > .nav-tabs {
+ border-top: 1px solid #ddd;
+}
+
+.tabs-below > .nav-tabs > li {
+ margin-top: -1px;
+ margin-bottom: 0;
+}
+
+.tabs-below > .nav-tabs > li > a {
+ -webkit-border-radius: 0 0 4px 4px;
+ -moz-border-radius: 0 0 4px 4px;
+ border-radius: 0 0 4px 4px;
+}
+
+.tabs-below > .nav-tabs > li > a:hover,
+.tabs-below > .nav-tabs > li > a:focus {
+ border-top-color: #ddd;
+ border-bottom-color: transparent;
+}
+
+.tabs-below > .nav-tabs > .active > a,
+.tabs-below > .nav-tabs > .active > a:hover,
+.tabs-below > .nav-tabs > .active > a:focus {
+ border-color: transparent #ddd #ddd #ddd;
+}
+
+.tabs-left > .nav-tabs > li,
+.tabs-right > .nav-tabs > li {
+ float: none;
+}
+
+.tabs-left > .nav-tabs > li > a,
+.tabs-right > .nav-tabs > li > a {
+ min-width: 74px;
+ margin-right: 0;
+ margin-bottom: 3px;
+}
+
+.tabs-left > .nav-tabs {
+ float: left;
+ margin-right: 19px;
+ border-right: 1px solid #ddd;
+}
+
+.tabs-left > .nav-tabs > li > a {
+ margin-right: -1px;
+ -webkit-border-radius: 4px 0 0 4px;
+ -moz-border-radius: 4px 0 0 4px;
+ border-radius: 4px 0 0 4px;
+}
+
+.tabs-left > .nav-tabs > li > a:hover,
+.tabs-left > .nav-tabs > li > a:focus {
+ border-color: #eeeeee #dddddd #eeeeee #eeeeee;
+}
+
+.tabs-left > .nav-tabs .active > a,
+.tabs-left > .nav-tabs .active > a:hover,
+.tabs-left > .nav-tabs .active > a:focus {
+ border-color: #ddd transparent #ddd #ddd;
+ *border-right-color: #ffffff;
+}
+
+.tabs-right > .nav-tabs {
+ float: right;
+ margin-left: 19px;
+ border-left: 1px solid #ddd;
+}
+
+.tabs-right > .nav-tabs > li > a {
+ margin-left: -1px;
+ -webkit-border-radius: 0 4px 4px 0;
+ -moz-border-radius: 0 4px 4px 0;
+ border-radius: 0 4px 4px 0;
+}
+
+.tabs-right > .nav-tabs > li > a:hover,
+.tabs-right > .nav-tabs > li > a:focus {
+ border-color: #eeeeee #eeeeee #eeeeee #dddddd;
+}
+
+.tabs-right > .nav-tabs .active > a,
+.tabs-right > .nav-tabs .active > a:hover,
+.tabs-right > .nav-tabs .active > a:focus {
+ border-color: #ddd #ddd #ddd transparent;
+ *border-left-color: #ffffff;
+}
+
+.nav > .disabled > a {
+ color: #999999;
+}
+
+.nav > .disabled > a:hover,
+.nav > .disabled > a:focus {
+ text-decoration: none;
+ cursor: default;
+ background-color: transparent;
+}
+
+.navbar {
+ *position: relative;
+ *z-index: 2;
+ margin-bottom: 20px;
+ overflow: visible;
+}
+
+.navbar-inner {
+ min-height: 40px;
+ padding-right: 20px;
+ padding-left: 20px;
+ background-color: #fafafa;
+ background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));
+ background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);
+ background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);
+ background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);
+ background-repeat: repeat-x;
+ border: 1px solid #d4d4d4;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);
+ *zoom: 1;
+ -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+ -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
+}
+
+.navbar-inner:before,
+.navbar-inner:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.navbar-inner:after {
+ clear: both;
+}
+
+.navbar .container {
+ width: auto;
+}
+
+.nav-collapse.collapse {
+ height: auto;
+ overflow: visible;
+}
+
+.navbar .brand {
+ display: block;
+ float: left;
+ padding: 10px 20px 10px;
+ margin-left: -20px;
+ font-size: 20px;
+ font-weight: 200;
+ color: #777777;
+ text-shadow: 0 1px 0 #ffffff;
+}
+
+.navbar .brand:hover,
+.navbar .brand:focus {
+ text-decoration: none;
+}
+
+.navbar-text {
+ margin-bottom: 0;
+ line-height: 40px;
+ color: #777777;
+}
+
+.navbar-link {
+ color: #777777;
+}
+
+.navbar-link:hover,
+.navbar-link:focus {
+ color: #333333;
+}
+
+.navbar .divider-vertical {
+ height: 40px;
+ margin: 0 9px;
+ border-right: 1px solid #ffffff;
+ border-left: 1px solid #f2f2f2;
+}
+
+.navbar .btn,
+.navbar .btn-group {
+ margin-top: 5px;
+}
+
+.navbar .btn-group .btn,
+.navbar .input-prepend .btn,
+.navbar .input-append .btn,
+.navbar .input-prepend .btn-group,
+.navbar .input-append .btn-group {
+ margin-top: 0;
+}
+
+.navbar-form {
+ margin-bottom: 0;
+ *zoom: 1;
+}
+
+.navbar-form:before,
+.navbar-form:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.navbar-form:after {
+ clear: both;
+}
+
+.navbar-form input,
+.navbar-form select,
+.navbar-form .radio,
+.navbar-form .checkbox {
+ margin-top: 5px;
+}
+
+.navbar-form input,
+.navbar-form select,
+.navbar-form .btn {
+ display: inline-block;
+ margin-bottom: 0;
+}
+
+.navbar-form input[type="image"],
+.navbar-form input[type="checkbox"],
+.navbar-form input[type="radio"] {
+ margin-top: 3px;
+}
+
+.navbar-form .input-append,
+.navbar-form .input-prepend {
+ margin-top: 5px;
+ white-space: nowrap;
+}
+
+.navbar-form .input-append input,
+.navbar-form .input-prepend input {
+ margin-top: 0;
+}
+
+.navbar-search {
+ position: relative;
+ float: left;
+ margin-top: 5px;
+ margin-bottom: 0;
+}
+
+.navbar-search .search-query {
+ padding: 4px 14px;
+ margin-bottom: 0;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 13px;
+ font-weight: normal;
+ line-height: 1;
+ -webkit-border-radius: 15px;
+ -moz-border-radius: 15px;
+ border-radius: 15px;
+}
+
+.navbar-static-top {
+ position: static;
+ margin-bottom: 0;
+}
+
+.navbar-static-top .navbar-inner {
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+ position: fixed;
+ right: 0;
+ left: 0;
+ z-index: 1030;
+ margin-bottom: 0;
+}
+
+.navbar-fixed-top .navbar-inner,
+.navbar-static-top .navbar-inner {
+ border-width: 0 0 1px;
+}
+
+.navbar-fixed-bottom .navbar-inner {
+ border-width: 1px 0 0;
+}
+
+.navbar-fixed-top .navbar-inner,
+.navbar-fixed-bottom .navbar-inner {
+ padding-right: 0;
+ padding-left: 0;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+}
+
+.navbar-static-top .container,
+.navbar-fixed-top .container,
+.navbar-fixed-bottom .container {
+ width: 940px;
+}
+
+.navbar-fixed-top {
+ top: 0;
+}
+
+.navbar-fixed-top .navbar-inner,
+.navbar-static-top .navbar-inner {
+ -webkit-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
+ -moz-box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
+ box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
+}
+
+.navbar-fixed-bottom {
+ bottom: 0;
+}
+
+.navbar-fixed-bottom .navbar-inner {
+ -webkit-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
+ -moz-box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
+ box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
+}
+
+.navbar .nav {
+ position: relative;
+ left: 0;
+ display: block;
+ float: left;
+ margin: 0 10px 0 0;
+}
+
+.navbar .nav.pull-right {
+ float: right;
+ margin-right: 0;
+}
+
+.navbar .nav > li {
+ float: left;
+}
+
+.navbar .nav > li > a {
+ float: none;
+ padding: 10px 15px 10px;
+ color: #777777;
+ text-decoration: none;
+ text-shadow: 0 1px 0 #ffffff;
+}
+
+.navbar .nav .dropdown-toggle .caret {
+ margin-top: 8px;
+}
+
+.navbar .nav > li > a:focus,
+.navbar .nav > li > a:hover {
+ color: #333333;
+ text-decoration: none;
+ background-color: transparent;
+}
+
+.navbar .nav > .active > a,
+.navbar .nav > .active > a:hover,
+.navbar .nav > .active > a:focus {
+ color: #555555;
+ text-decoration: none;
+ background-color: #e5e5e5;
+ -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
+ -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
+ box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
+}
+
+.navbar .btn-navbar {
+ display: none;
+ float: right;
+ padding: 7px 10px;
+ margin-right: 5px;
+ margin-left: 5px;
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #ededed;
+ *background-color: #e5e5e5;
+ background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));
+ background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);
+ background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);
+ background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);
+ background-repeat: repeat-x;
+ border-color: #e5e5e5 #e5e5e5 #bfbfbf;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
+ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);
+}
+
+.navbar .btn-navbar:hover,
+.navbar .btn-navbar:focus,
+.navbar .btn-navbar:active,
+.navbar .btn-navbar.active,
+.navbar .btn-navbar.disabled,
+.navbar .btn-navbar[disabled] {
+ color: #ffffff;
+ background-color: #e5e5e5;
+ *background-color: #d9d9d9;
+}
+
+.navbar .btn-navbar:active,
+.navbar .btn-navbar.active {
+ background-color: #cccccc \9;
+}
+
+.navbar .btn-navbar .icon-bar {
+ display: block;
+ width: 18px;
+ height: 2px;
+ background-color: #f5f5f5;
+ -webkit-border-radius: 1px;
+ -moz-border-radius: 1px;
+ border-radius: 1px;
+ -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
+ -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
+}
+
+.btn-navbar .icon-bar + .icon-bar {
+ margin-top: 3px;
+}
+
+.navbar .nav > li > .dropdown-menu:before {
+ position: absolute;
+ top: -7px;
+ left: 9px;
+ display: inline-block;
+ border-right: 7px solid transparent;
+ border-bottom: 7px solid #ccc;
+ border-left: 7px solid transparent;
+ border-bottom-color: rgba(0, 0, 0, 0.2);
+ content: '';
+}
+
+.navbar .nav > li > .dropdown-menu:after {
+ position: absolute;
+ top: -6px;
+ left: 10px;
+ display: inline-block;
+ border-right: 6px solid transparent;
+ border-bottom: 6px solid #ffffff;
+ border-left: 6px solid transparent;
+ content: '';
+}
+
+.navbar-fixed-bottom .nav > li > .dropdown-menu:before {
+ top: auto;
+ bottom: -7px;
+ border-top: 7px solid #ccc;
+ border-bottom: 0;
+ border-top-color: rgba(0, 0, 0, 0.2);
+}
+
+.navbar-fixed-bottom .nav > li > .dropdown-menu:after {
+ top: auto;
+ bottom: -6px;
+ border-top: 6px solid #ffffff;
+ border-bottom: 0;
+}
+
+.navbar .nav li.dropdown > a:hover .caret,
+.navbar .nav li.dropdown > a:focus .caret {
+ border-top-color: #333333;
+ border-bottom-color: #333333;
+}
+
+.navbar .nav li.dropdown.open > .dropdown-toggle,
+.navbar .nav li.dropdown.active > .dropdown-toggle,
+.navbar .nav li.dropdown.open.active > .dropdown-toggle {
+ color: #555555;
+ background-color: #e5e5e5;
+}
+
+.navbar .nav li.dropdown > .dropdown-toggle .caret {
+ border-top-color: #777777;
+ border-bottom-color: #777777;
+}
+
+.navbar .nav li.dropdown.open > .dropdown-toggle .caret,
+.navbar .nav li.dropdown.active > .dropdown-toggle .caret,
+.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {
+ border-top-color: #555555;
+ border-bottom-color: #555555;
+}
+
+.navbar .pull-right > li > .dropdown-menu,
+.navbar .nav > li > .dropdown-menu.pull-right {
+ right: 0;
+ left: auto;
+}
+
+.navbar .pull-right > li > .dropdown-menu:before,
+.navbar .nav > li > .dropdown-menu.pull-right:before {
+ right: 12px;
+ left: auto;
+}
+
+.navbar .pull-right > li > .dropdown-menu:after,
+.navbar .nav > li > .dropdown-menu.pull-right:after {
+ right: 13px;
+ left: auto;
+}
+
+.navbar .pull-right > li > .dropdown-menu .dropdown-menu,
+.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {
+ right: 100%;
+ left: auto;
+ margin-right: -1px;
+ margin-left: 0;
+ -webkit-border-radius: 6px 0 6px 6px;
+ -moz-border-radius: 6px 0 6px 6px;
+ border-radius: 6px 0 6px 6px;
+}
+
+.navbar-inverse .navbar-inner {
+ background-color: #1b1b1b;
+ background-image: -moz-linear-gradient(top, #222222, #111111);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));
+ background-image: -webkit-linear-gradient(top, #222222, #111111);
+ background-image: -o-linear-gradient(top, #222222, #111111);
+ background-image: linear-gradient(to bottom, #222222, #111111);
+ background-repeat: repeat-x;
+ border-color: #252525;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);
+}
+
+.navbar-inverse .brand,
+.navbar-inverse .nav > li > a {
+ color: #999999;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+
+.navbar-inverse .brand:hover,
+.navbar-inverse .nav > li > a:hover,
+.navbar-inverse .brand:focus,
+.navbar-inverse .nav > li > a:focus {
+ color: #ffffff;
+}
+
+.navbar-inverse .brand {
+ color: #999999;
+}
+
+.navbar-inverse .navbar-text {
+ color: #999999;
+}
+
+.navbar-inverse .nav > li > a:focus,
+.navbar-inverse .nav > li > a:hover {
+ color: #ffffff;
+ background-color: transparent;
+}
+
+.navbar-inverse .nav .active > a,
+.navbar-inverse .nav .active > a:hover,
+.navbar-inverse .nav .active > a:focus {
+ color: #ffffff;
+ background-color: #111111;
+}
+
+.navbar-inverse .navbar-link {
+ color: #999999;
+}
+
+.navbar-inverse .navbar-link:hover,
+.navbar-inverse .navbar-link:focus {
+ color: #ffffff;
+}
+
+.navbar-inverse .divider-vertical {
+ border-right-color: #222222;
+ border-left-color: #111111;
+}
+
+.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,
+.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,
+.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {
+ color: #ffffff;
+ background-color: #111111;
+}
+
+.navbar-inverse .nav li.dropdown > a:hover .caret,
+.navbar-inverse .nav li.dropdown > a:focus .caret {
+ border-top-color: #ffffff;
+ border-bottom-color: #ffffff;
+}
+
+.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {
+ border-top-color: #999999;
+ border-bottom-color: #999999;
+}
+
+.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,
+.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,
+.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {
+ border-top-color: #ffffff;
+ border-bottom-color: #ffffff;
+}
+
+.navbar-inverse .navbar-search .search-query {
+ color: #ffffff;
+ background-color: #515151;
+ border-color: #111111;
+ -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);
+ -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);
+ -webkit-transition: none;
+ -moz-transition: none;
+ -o-transition: none;
+ transition: none;
+}
+
+.navbar-inverse .navbar-search .search-query:-moz-placeholder {
+ color: #cccccc;
+}
+
+.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {
+ color: #cccccc;
+}
+
+.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {
+ color: #cccccc;
+}
+
+.navbar-inverse .navbar-search .search-query:focus,
+.navbar-inverse .navbar-search .search-query.focused {
+ padding: 5px 15px;
+ color: #333333;
+ text-shadow: 0 1px 0 #ffffff;
+ background-color: #ffffff;
+ border: 0;
+ outline: 0;
+ -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
+ -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
+ box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
+}
+
+.navbar-inverse .btn-navbar {
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #0e0e0e;
+ *background-color: #040404;
+ background-image: -moz-linear-gradient(top, #151515, #040404);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));
+ background-image: -webkit-linear-gradient(top, #151515, #040404);
+ background-image: -o-linear-gradient(top, #151515, #040404);
+ background-image: linear-gradient(to bottom, #151515, #040404);
+ background-repeat: repeat-x;
+ border-color: #040404 #040404 #000000;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+}
+
+.navbar-inverse .btn-navbar:hover,
+.navbar-inverse .btn-navbar:focus,
+.navbar-inverse .btn-navbar:active,
+.navbar-inverse .btn-navbar.active,
+.navbar-inverse .btn-navbar.disabled,
+.navbar-inverse .btn-navbar[disabled] {
+ color: #ffffff;
+ background-color: #040404;
+ *background-color: #000000;
+}
+
+.navbar-inverse .btn-navbar:active,
+.navbar-inverse .btn-navbar.active {
+ background-color: #000000 \9;
+}
+
+.breadcrumb {
+ padding: 8px 15px;
+ margin: 0 0 20px;
+ list-style: none;
+ background-color: #f5f5f5;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.breadcrumb > li {
+ display: inline-block;
+ *display: inline;
+ text-shadow: 0 1px 0 #ffffff;
+ *zoom: 1;
+}
+
+.breadcrumb > li > .divider {
+ padding: 0 5px;
+ color: #ccc;
+}
+
+.breadcrumb > .active {
+ color: #999999;
+}
+
+.pagination {
+ margin: 20px 0;
+}
+
+.pagination ul {
+ display: inline-block;
+ *display: inline;
+ margin-bottom: 0;
+ margin-left: 0;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ *zoom: 1;
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+
+.pagination ul > li {
+ display: inline;
+}
+
+.pagination ul > li > a,
+.pagination ul > li > span {
+ float: left;
+ padding: 4px 12px;
+ line-height: 20px;
+ text-decoration: none;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+ border-left-width: 0;
+}
+
+.pagination ul > li > a:hover,
+.pagination ul > li > a:focus,
+.pagination ul > .active > a,
+.pagination ul > .active > span {
+ background-color: #f5f5f5;
+}
+
+.pagination ul > .active > a,
+.pagination ul > .active > span {
+ color: #999999;
+ cursor: default;
+}
+
+.pagination ul > .disabled > span,
+.pagination ul > .disabled > a,
+.pagination ul > .disabled > a:hover,
+.pagination ul > .disabled > a:focus {
+ color: #999999;
+ cursor: default;
+ background-color: transparent;
+}
+
+.pagination ul > li:first-child > a,
+.pagination ul > li:first-child > span {
+ border-left-width: 1px;
+ -webkit-border-bottom-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+ -webkit-border-top-left-radius: 4px;
+ border-top-left-radius: 4px;
+ -moz-border-radius-bottomleft: 4px;
+ -moz-border-radius-topleft: 4px;
+}
+
+.pagination ul > li:last-child > a,
+.pagination ul > li:last-child > span {
+ -webkit-border-top-right-radius: 4px;
+ border-top-right-radius: 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ -moz-border-radius-topright: 4px;
+ -moz-border-radius-bottomright: 4px;
+}
+
+.pagination-centered {
+ text-align: center;
+}
+
+.pagination-right {
+ text-align: right;
+}
+
+.pagination-large ul > li > a,
+.pagination-large ul > li > span {
+ padding: 11px 19px;
+ font-size: 17.5px;
+}
+
+.pagination-large ul > li:first-child > a,
+.pagination-large ul > li:first-child > span {
+ -webkit-border-bottom-left-radius: 6px;
+ border-bottom-left-radius: 6px;
+ -webkit-border-top-left-radius: 6px;
+ border-top-left-radius: 6px;
+ -moz-border-radius-bottomleft: 6px;
+ -moz-border-radius-topleft: 6px;
+}
+
+.pagination-large ul > li:last-child > a,
+.pagination-large ul > li:last-child > span {
+ -webkit-border-top-right-radius: 6px;
+ border-top-right-radius: 6px;
+ -webkit-border-bottom-right-radius: 6px;
+ border-bottom-right-radius: 6px;
+ -moz-border-radius-topright: 6px;
+ -moz-border-radius-bottomright: 6px;
+}
+
+.pagination-mini ul > li:first-child > a,
+.pagination-small ul > li:first-child > a,
+.pagination-mini ul > li:first-child > span,
+.pagination-small ul > li:first-child > span {
+ -webkit-border-bottom-left-radius: 3px;
+ border-bottom-left-radius: 3px;
+ -webkit-border-top-left-radius: 3px;
+ border-top-left-radius: 3px;
+ -moz-border-radius-bottomleft: 3px;
+ -moz-border-radius-topleft: 3px;
+}
+
+.pagination-mini ul > li:last-child > a,
+.pagination-small ul > li:last-child > a,
+.pagination-mini ul > li:last-child > span,
+.pagination-small ul > li:last-child > span {
+ -webkit-border-top-right-radius: 3px;
+ border-top-right-radius: 3px;
+ -webkit-border-bottom-right-radius: 3px;
+ border-bottom-right-radius: 3px;
+ -moz-border-radius-topright: 3px;
+ -moz-border-radius-bottomright: 3px;
+}
+
+.pagination-small ul > li > a,
+.pagination-small ul > li > span {
+ padding: 2px 10px;
+ font-size: 11.9px;
+}
+
+.pagination-mini ul > li > a,
+.pagination-mini ul > li > span {
+ padding: 0 6px;
+ font-size: 10.5px;
+}
+
+.pager {
+ margin: 20px 0;
+ text-align: center;
+ list-style: none;
+ *zoom: 1;
+}
+
+.pager:before,
+.pager:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.pager:after {
+ clear: both;
+}
+
+.pager li {
+ display: inline;
+}
+
+.pager li > a,
+.pager li > span {
+ display: inline-block;
+ padding: 5px 14px;
+ background-color: #fff;
+ border: 1px solid #ddd;
+ -webkit-border-radius: 15px;
+ -moz-border-radius: 15px;
+ border-radius: 15px;
+}
+
+.pager li > a:hover,
+.pager li > a:focus {
+ text-decoration: none;
+ background-color: #f5f5f5;
+}
+
+.pager .next > a,
+.pager .next > span {
+ float: right;
+}
+
+.pager .previous > a,
+.pager .previous > span {
+ float: left;
+}
+
+.pager .disabled > a,
+.pager .disabled > a:hover,
+.pager .disabled > a:focus,
+.pager .disabled > span {
+ color: #999999;
+ cursor: default;
+ background-color: #fff;
+}
+
+.modal-backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1040;
+ background-color: #000000;
+}
+
+.modal-backdrop.fade {
+ opacity: 0;
+}
+
+.modal-backdrop,
+.modal-backdrop.fade.in {
+ opacity: 0.8;
+ filter: alpha(opacity=80);
+}
+
+.modal {
+ position: fixed;
+ top: 10%;
+ left: 50%;
+ z-index: 1050;
+ width: 560px;
+ margin-left: -280px;
+ background-color: #ffffff;
+ border: 1px solid #999;
+ border: 1px solid rgba(0, 0, 0, 0.3);
+ *border: 1px solid #999;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ outline: none;
+ -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+ -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+ box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding-box;
+ background-clip: padding-box;
+}
+
+.modal.fade {
+ top: -25%;
+ -webkit-transition: opacity 0.3s linear, top 0.3s ease-out;
+ -moz-transition: opacity 0.3s linear, top 0.3s ease-out;
+ -o-transition: opacity 0.3s linear, top 0.3s ease-out;
+ transition: opacity 0.3s linear, top 0.3s ease-out;
+}
+
+.modal.fade.in {
+ top: 10%;
+}
+
+.modal-header {
+ padding: 9px 15px;
+ border-bottom: 1px solid #eee;
+}
+
+.modal-header .close {
+ margin-top: 2px;
+}
+
+.modal-header h3 {
+ margin: 0;
+ line-height: 30px;
+}
+
+.modal-body {
+ position: relative;
+ max-height: 400px;
+ padding: 15px;
+ overflow-y: auto;
+}
+
+.modal-form {
+ margin-bottom: 0;
+}
+
+.modal-footer {
+ padding: 14px 15px 15px;
+ margin-bottom: 0;
+ text-align: right;
+ background-color: #f5f5f5;
+ border-top: 1px solid #ddd;
+ -webkit-border-radius: 0 0 6px 6px;
+ -moz-border-radius: 0 0 6px 6px;
+ border-radius: 0 0 6px 6px;
+ *zoom: 1;
+ -webkit-box-shadow: inset 0 1px 0 #ffffff;
+ -moz-box-shadow: inset 0 1px 0 #ffffff;
+ box-shadow: inset 0 1px 0 #ffffff;
+}
+
+.modal-footer:before,
+.modal-footer:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.modal-footer:after {
+ clear: both;
+}
+
+.modal-footer .btn + .btn {
+ margin-bottom: 0;
+ margin-left: 5px;
+}
+
+.modal-footer .btn-group .btn + .btn {
+ margin-left: -1px;
+}
+
+.modal-footer .btn-block + .btn-block {
+ margin-left: 0;
+}
+
+.tooltip {
+ position: absolute;
+ z-index: 1030;
+ display: block;
+ font-size: 11px;
+ line-height: 1.4;
+ opacity: 0;
+ filter: alpha(opacity=0);
+ visibility: visible;
+}
+
+.tooltip.in {
+ opacity: 0.8;
+ filter: alpha(opacity=80);
+}
+
+.tooltip.top {
+ padding: 5px 0;
+ margin-top: -3px;
+}
+
+.tooltip.right {
+ padding: 0 5px;
+ margin-left: 3px;
+}
+
+.tooltip.bottom {
+ padding: 5px 0;
+ margin-top: 3px;
+}
+
+.tooltip.left {
+ padding: 0 5px;
+ margin-left: -3px;
+}
+
+.tooltip-inner {
+ max-width: 200px;
+ padding: 8px;
+ color: #ffffff;
+ text-align: center;
+ text-decoration: none;
+ background-color: #000000;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.tooltip-arrow {
+ position: absolute;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+}
+
+.tooltip.top .tooltip-arrow {
+ bottom: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-top-color: #000000;
+ border-width: 5px 5px 0;
+}
+
+.tooltip.right .tooltip-arrow {
+ top: 50%;
+ left: 0;
+ margin-top: -5px;
+ border-right-color: #000000;
+ border-width: 5px 5px 5px 0;
+}
+
+.tooltip.left .tooltip-arrow {
+ top: 50%;
+ right: 0;
+ margin-top: -5px;
+ border-left-color: #000000;
+ border-width: 5px 0 5px 5px;
+}
+
+.tooltip.bottom .tooltip-arrow {
+ top: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-bottom-color: #000000;
+ border-width: 0 5px 5px;
+}
+
+.popover {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 1010;
+ display: none;
+ max-width: 276px;
+ padding: 1px;
+ text-align: left;
+ white-space: normal;
+ background-color: #ffffff;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding;
+ background-clip: padding-box;
+}
+
+.popover.top {
+ margin-top: -10px;
+}
+
+.popover.right {
+ margin-left: 10px;
+}
+
+.popover.bottom {
+ margin-top: 10px;
+}
+
+.popover.left {
+ margin-left: -10px;
+}
+
+.popover-title {
+ padding: 8px 14px;
+ margin: 0;
+ font-size: 14px;
+ font-weight: normal;
+ line-height: 18px;
+ background-color: #f7f7f7;
+ border-bottom: 1px solid #ebebeb;
+ -webkit-border-radius: 5px 5px 0 0;
+ -moz-border-radius: 5px 5px 0 0;
+ border-radius: 5px 5px 0 0;
+}
+
+.popover-title:empty {
+ display: none;
+}
+
+.popover-content {
+ padding: 9px 14px;
+}
+
+.popover .arrow,
+.popover .arrow:after {
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+}
+
+.popover .arrow {
+ border-width: 11px;
+}
+
+.popover .arrow:after {
+ border-width: 10px;
+ content: "";
+}
+
+.popover.top .arrow {
+ bottom: -11px;
+ left: 50%;
+ margin-left: -11px;
+ border-top-color: #999;
+ border-top-color: rgba(0, 0, 0, 0.25);
+ border-bottom-width: 0;
+}
+
+.popover.top .arrow:after {
+ bottom: 1px;
+ margin-left: -10px;
+ border-top-color: #ffffff;
+ border-bottom-width: 0;
+}
+
+.popover.right .arrow {
+ top: 50%;
+ left: -11px;
+ margin-top: -11px;
+ border-right-color: #999;
+ border-right-color: rgba(0, 0, 0, 0.25);
+ border-left-width: 0;
+}
+
+.popover.right .arrow:after {
+ bottom: -10px;
+ left: 1px;
+ border-right-color: #ffffff;
+ border-left-width: 0;
+}
+
+.popover.bottom .arrow {
+ top: -11px;
+ left: 50%;
+ margin-left: -11px;
+ border-bottom-color: #999;
+ border-bottom-color: rgba(0, 0, 0, 0.25);
+ border-top-width: 0;
+}
+
+.popover.bottom .arrow:after {
+ top: 1px;
+ margin-left: -10px;
+ border-bottom-color: #ffffff;
+ border-top-width: 0;
+}
+
+.popover.left .arrow {
+ top: 50%;
+ right: -11px;
+ margin-top: -11px;
+ border-left-color: #999;
+ border-left-color: rgba(0, 0, 0, 0.25);
+ border-right-width: 0;
+}
+
+.popover.left .arrow:after {
+ right: 1px;
+ bottom: -10px;
+ border-left-color: #ffffff;
+ border-right-width: 0;
+}
+
+.thumbnails {
+ margin-left: -20px;
+ list-style: none;
+ *zoom: 1;
+}
+
+.thumbnails:before,
+.thumbnails:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.thumbnails:after {
+ clear: both;
+}
+
+.row-fluid .thumbnails {
+ margin-left: 0;
+}
+
+.thumbnails > li {
+ float: left;
+ margin-bottom: 20px;
+ margin-left: 20px;
+}
+
+.thumbnail {
+ display: block;
+ padding: 4px;
+ line-height: 20px;
+ border: 1px solid #ddd;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
+ -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
+ -webkit-transition: all 0.2s ease-in-out;
+ -moz-transition: all 0.2s ease-in-out;
+ -o-transition: all 0.2s ease-in-out;
+ transition: all 0.2s ease-in-out;
+}
+
+a.thumbnail:hover,
+a.thumbnail:focus {
+ border-color: #0088cc;
+ -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
+ -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
+ box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
+}
+
+.thumbnail > img {
+ display: block;
+ max-width: 100%;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+.thumbnail .caption {
+ padding: 9px;
+ color: #555555;
+}
+
+.media,
+.media-body {
+ overflow: hidden;
+ *overflow: visible;
+ zoom: 1;
+}
+
+.media,
+.media .media {
+ margin-top: 15px;
+}
+
+.media:first-child {
+ margin-top: 0;
+}
+
+.media-object {
+ display: block;
+}
+
+.media-heading {
+ margin: 0 0 5px;
+}
+
+.media > .pull-left {
+ margin-right: 10px;
+}
+
+.media > .pull-right {
+ margin-left: 10px;
+}
+
+.media-list {
+ margin-left: 0;
+ list-style: none;
+}
+
+.label,
+.badge {
+ display: inline-block;
+ padding: 2px 4px;
+ font-size: 11.844px;
+ font-weight: bold;
+ line-height: 14px;
+ color: #ffffff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ white-space: nowrap;
+ vertical-align: baseline;
+ background-color: #999999;
+}
+
+.label {
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+
+.badge {
+ padding-right: 9px;
+ padding-left: 9px;
+ -webkit-border-radius: 9px;
+ -moz-border-radius: 9px;
+ border-radius: 9px;
+}
+
+.label:empty,
+.badge:empty {
+ display: none;
+}
+
+a.label:hover,
+a.label:focus,
+a.badge:hover,
+a.badge:focus {
+ color: #ffffff;
+ text-decoration: none;
+ cursor: pointer;
+}
+
+.label-important,
+.badge-important {
+ background-color: #b94a48;
+}
+
+.label-important[href],
+.badge-important[href] {
+ background-color: #953b39;
+}
+
+.label-warning,
+.badge-warning {
+ background-color: #f89406;
+}
+
+.label-warning[href],
+.badge-warning[href] {
+ background-color: #c67605;
+}
+
+.label-success,
+.badge-success {
+ background-color: #468847;
+}
+
+.label-success[href],
+.badge-success[href] {
+ background-color: #356635;
+}
+
+.label-info,
+.badge-info {
+ background-color: #3a87ad;
+}
+
+.label-info[href],
+.badge-info[href] {
+ background-color: #2d6987;
+}
+
+.label-inverse,
+.badge-inverse {
+ background-color: #333333;
+}
+
+.label-inverse[href],
+.badge-inverse[href] {
+ background-color: #1a1a1a;
+}
+
+.btn .label,
+.btn .badge {
+ position: relative;
+ top: -1px;
+}
+
+.btn-mini .label,
+.btn-mini .badge {
+ top: 0;
+}
+
+@-webkit-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+
+@-moz-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+
+@-ms-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+
+@-o-keyframes progress-bar-stripes {
+ from {
+ background-position: 0 0;
+ }
+ to {
+ background-position: 40px 0;
+ }
+}
+
+@keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+
+.progress {
+ height: 20px;
+ margin-bottom: 20px;
+ overflow: hidden;
+ background-color: #f7f7f7;
+ background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));
+ background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);
+ background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);
+ background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);
+ background-repeat: repeat-x;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);
+ -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+ -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+}
+
+.progress .bar {
+ float: left;
+ width: 0;
+ height: 100%;
+ font-size: 12px;
+ color: #ffffff;
+ text-align: center;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ background-color: #0e90d2;
+ background-image: -moz-linear-gradient(top, #149bdf, #0480be);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));
+ background-image: -webkit-linear-gradient(top, #149bdf, #0480be);
+ background-image: -o-linear-gradient(top, #149bdf, #0480be);
+ background-image: linear-gradient(to bottom, #149bdf, #0480be);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);
+ -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+ -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ -webkit-transition: width 0.6s ease;
+ -moz-transition: width 0.6s ease;
+ -o-transition: width 0.6s ease;
+ transition: width 0.6s ease;
+}
+
+.progress .bar + .bar {
+ -webkit-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+ -moz-box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+ box-shadow: inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+}
+
+.progress-striped .bar {
+ background-color: #149bdf;
+ background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ -webkit-background-size: 40px 40px;
+ -moz-background-size: 40px 40px;
+ -o-background-size: 40px 40px;
+ background-size: 40px 40px;
+}
+
+.progress.active .bar {
+ -webkit-animation: progress-bar-stripes 2s linear infinite;
+ -moz-animation: progress-bar-stripes 2s linear infinite;
+ -ms-animation: progress-bar-stripes 2s linear infinite;
+ -o-animation: progress-bar-stripes 2s linear infinite;
+ animation: progress-bar-stripes 2s linear infinite;
+}
+
+.progress-danger .bar,
+.progress .bar-danger {
+ background-color: #dd514c;
+ background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));
+ background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
+ background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
+ background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);
+}
+
+.progress-danger.progress-striped .bar,
+.progress-striped .bar-danger {
+ background-color: #ee5f5b;
+ background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.progress-success .bar,
+.progress .bar-success {
+ background-color: #5eb95e;
+ background-image: -moz-linear-gradient(top, #62c462, #57a957);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));
+ background-image: -webkit-linear-gradient(top, #62c462, #57a957);
+ background-image: -o-linear-gradient(top, #62c462, #57a957);
+ background-image: linear-gradient(to bottom, #62c462, #57a957);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);
+}
+
+.progress-success.progress-striped .bar,
+.progress-striped .bar-success {
+ background-color: #62c462;
+ background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.progress-info .bar,
+.progress .bar-info {
+ background-color: #4bb1cf;
+ background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));
+ background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
+ background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
+ background-image: linear-gradient(to bottom, #5bc0de, #339bb9);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);
+}
+
+.progress-info.progress-striped .bar,
+.progress-striped .bar-info {
+ background-color: #5bc0de;
+ background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.progress-warning .bar,
+.progress .bar-warning {
+ background-color: #faa732;
+ background-image: -moz-linear-gradient(top, #fbb450, #f89406);
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
+ background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
+ background-image: -o-linear-gradient(top, #fbb450, #f89406);
+ background-image: linear-gradient(to bottom, #fbb450, #f89406);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
+}
+
+.progress-warning.progress-striped .bar,
+.progress-striped .bar-warning {
+ background-color: #fbb450;
+ background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+
+.accordion {
+ margin-bottom: 20px;
+}
+
+.accordion-group {
+ margin-bottom: 2px;
+ border: 1px solid #e5e5e5;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+
+.accordion-heading {
+ border-bottom: 0;
+}
+
+.accordion-heading .accordion-toggle {
+ display: block;
+ padding: 8px 15px;
+}
+
+.accordion-toggle {
+ cursor: pointer;
+}
+
+.accordion-inner {
+ padding: 9px 15px;
+ border-top: 1px solid #e5e5e5;
+}
+
+.carousel {
+ position: relative;
+ margin-bottom: 20px;
+ line-height: 1;
+}
+
+.carousel-inner {
+ position: relative;
+ width: 100%;
+ overflow: hidden;
+}
+
+.carousel-inner > .item {
+ position: relative;
+ display: none;
+ -webkit-transition: 0.6s ease-in-out left;
+ -moz-transition: 0.6s ease-in-out left;
+ -o-transition: 0.6s ease-in-out left;
+ transition: 0.6s ease-in-out left;
+}
+
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+ display: block;
+ line-height: 1;
+}
+
+.carousel-inner > .active,
+.carousel-inner > .next,
+.carousel-inner > .prev {
+ display: block;
+}
+
+.carousel-inner > .active {
+ left: 0;
+}
+
+.carousel-inner > .next,
+.carousel-inner > .prev {
+ position: absolute;
+ top: 0;
+ width: 100%;
+}
+
+.carousel-inner > .next {
+ left: 100%;
+}
+
+.carousel-inner > .prev {
+ left: -100%;
+}
+
+.carousel-inner > .next.left,
+.carousel-inner > .prev.right {
+ left: 0;
+}
+
+.carousel-inner > .active.left {
+ left: -100%;
+}
+
+.carousel-inner > .active.right {
+ left: 100%;
+}
+
+.carousel-control {
+ position: absolute;
+ top: 40%;
+ left: 15px;
+ width: 40px;
+ height: 40px;
+ margin-top: -20px;
+ font-size: 60px;
+ font-weight: 100;
+ line-height: 30px;
+ color: #ffffff;
+ text-align: center;
+ background: #222222;
+ border: 3px solid #ffffff;
+ -webkit-border-radius: 23px;
+ -moz-border-radius: 23px;
+ border-radius: 23px;
+ opacity: 0.5;
+ filter: alpha(opacity=50);
+}
+
+.carousel-control.right {
+ right: 15px;
+ left: auto;
+}
+
+.carousel-control:hover,
+.carousel-control:focus {
+ color: #ffffff;
+ text-decoration: none;
+ opacity: 0.9;
+ filter: alpha(opacity=90);
+}
+
+.carousel-indicators {
+ position: absolute;
+ top: 15px;
+ right: 15px;
+ z-index: 5;
+ margin: 0;
+ list-style: none;
+}
+
+.carousel-indicators li {
+ display: block;
+ float: left;
+ width: 10px;
+ height: 10px;
+ margin-left: 5px;
+ text-indent: -999px;
+ background-color: #ccc;
+ background-color: rgba(255, 255, 255, 0.25);
+ border-radius: 5px;
+}
+
+.carousel-indicators .active {
+ background-color: #fff;
+}
+
+.carousel-caption {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ padding: 15px;
+ background: #333333;
+ background: rgba(0, 0, 0, 0.75);
+}
+
+.carousel-caption h4,
+.carousel-caption p {
+ line-height: 20px;
+ color: #ffffff;
+}
+
+.carousel-caption h4 {
+ margin: 0 0 5px;
+}
+
+.carousel-caption p {
+ margin-bottom: 0;
+}
+
+.hero-unit {
+ padding: 60px;
+ margin-bottom: 30px;
+ font-size: 18px;
+ font-weight: 200;
+ line-height: 30px;
+ color: inherit;
+ background-color: #eeeeee;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+}
+
+.hero-unit h1 {
+ margin-bottom: 0;
+ font-size: 60px;
+ line-height: 1;
+ letter-spacing: -1px;
+ color: inherit;
+}
+
+.hero-unit li {
+ line-height: 30px;
+}
+
+.pull-right {
+ float: right;
+}
+
+.pull-left {
+ float: left;
+}
+
+.hide {
+ display: none;
+}
+
+.show {
+ display: block;
+}
+
+.invisible {
+ visibility: hidden;
+}
+
+.affix {
+ position: fixed;
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap.min.css b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap.min.css
new file mode 100644
index 0000000..c10c7f4
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap.min.css
@@ -0,0 +1,9 @@
+/*!
+ * Bootstrap v2.3.1
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover,a:focus{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:hover,a.muted:focus{color:#808080}.text-warning{color:#c09853}a.text-warning:hover,a.text-warning:focus{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover,a.text-error:focus{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover,a.text-info:focus{color:#2d6987}.text-success{color:#468847}a.text-success:hover,a.text-success:focus{color:#356635}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h3{font-size:24.5px}h4{font-size:17.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;padding-right:5px;padding-left:5px;*zoom:1}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.checkbox{min-height:20px;padding-left:20px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left}.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{display:inline-block;margin-bottom:10px;font-size:0;white-space:nowrap;vertical-align:middle}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu,.input-append .popover,.input-prepend .popover{font-size:14px}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child,.table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover>td,.table-hover tbody tr:hover>th{background-color:#f5f5f5}table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success>td{background-color:#dff0d8}.table tbody tr.error>td{background-color:#f2dede}.table tbody tr.warning>td{background-color:#fcf8e3}.table tbody tr.info>td{background-color:#d9edf7}.table-hover tbody tr.success:hover>td{background-color:#d0e9c6}.table-hover tbody tr.error:hover>td{background-color:#ebcccc}.table-hover tbody tr.warning:hover>td{background-color:#faf2cc}.table-hover tbody tr.info:hover>td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:focus>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>li>a:focus>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:focus>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"],.dropdown-submenu:focus>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{width:16px;background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open{*z-index:1000}.open>.dropdown-menu{display:block}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*border:0;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover,.btn:focus{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0}.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.btn-mini .caret,.btn-small .caret{margin-top:8px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success h4{color:#468847}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover,.nav-list>.active>a:focus{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover,.nav-pills>.active>a:focus{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover,.nav-tabs.nav-stacked>li>a:focus{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover,.nav>.dropdown.active>a:focus{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover,.nav>li.dropdown.open.active>a:focus{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret,.nav li.dropdown.open a:focus .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover,.tabs-below>.nav-tabs>li>a:focus{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover,.tabs-left>.nav-tabs>li>a:focus{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover,.tabs-right>.nav-tabs>li>a:focus{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs .active>a:focus{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover,.nav>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover,.navbar-link:focus{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn,.navbar .input-prepend .btn-group,.navbar .input-append .btn-group{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:focus,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover,.navbar-inverse .brand:focus,.navbar-inverse .nav>li>a:focus{color:#fff}.navbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-moz-linear-gradient(top,#151515,#040404);background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:focus,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>li>a:focus,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>a:focus{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:10%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;z-index:1030;display:block;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-title:empty{display:none}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover,a.thumbnail:focus{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#555}.media,.media-body{overflow:hidden;*overflow:visible;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{margin-left:0;list-style:none}.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding-right:9px;padding-left:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}.btn .label,.btn .badge{position:relative;top:-1px}.btn-mini .label,.btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-indicators{position:absolute;top:15px;right:15px;z-index:5;margin:0;list-style:none}.carousel-indicators li{display:block;float:left;width:10px;height:10px;margin-left:5px;text-indent:-999px;background-color:#ccc;background-color:rgba(255,255,255,0.25);border-radius:5px}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit li{line-height:30px}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap-responsive.css b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap-responsive.css
new file mode 100644
index 0000000..fcd72f7
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap-responsive.css
@@ -0,0 +1,1109 @@
+/*!
+ * Bootstrap Responsive v2.3.1
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */
+
+.clearfix {
+ *zoom: 1;
+}
+
+.clearfix:before,
+.clearfix:after {
+ display: table;
+ line-height: 0;
+ content: "";
+}
+
+.clearfix:after {
+ clear: both;
+}
+
+.hide-text {
+ font: 0/0 a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0;
+}
+
+.input-block-level {
+ display: block;
+ width: 100%;
+ min-height: 30px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+@-ms-viewport {
+ width: device-width;
+}
+
+.hidden {
+ display: none;
+ visibility: hidden;
+}
+
+.visible-phone {
+ display: none !important;
+}
+
+.visible-tablet {
+ display: none !important;
+}
+
+.hidden-desktop {
+ display: none !important;
+}
+
+.visible-desktop {
+ display: inherit !important;
+}
+
+@media (min-width: 768px) and (max-width: 979px) {
+ .hidden-desktop {
+ display: inherit !important;
+ }
+ .visible-desktop {
+ display: none !important ;
+ }
+ .visible-tablet {
+ display: inherit !important;
+ }
+ .hidden-tablet {
+ display: none !important;
+ }
+}
+
+@media (max-width: 767px) {
+ .hidden-desktop {
+ display: inherit !important;
+ }
+ .visible-desktop {
+ display: none !important;
+ }
+ .visible-phone {
+ display: inherit !important;
+ }
+ .hidden-phone {
+ display: none !important;
+ }
+}
+
+.visible-print {
+ display: none !important;
+}
+
+@media print {
+ .visible-print {
+ display: inherit !important;
+ }
+ .hidden-print {
+ display: none !important;
+ }
+}
+
+@media (min-width: 1200px) {
+ .row {
+ margin-left: -30px;
+ *zoom: 1;
+ }
+ .row:before,
+ .row:after {
+ display: table;
+ line-height: 0;
+ content: "";
+ }
+ .row:after {
+ clear: both;
+ }
+ [class*="span"] {
+ float: left;
+ min-height: 1px;
+ margin-left: 30px;
+ }
+ .container,
+ .navbar-static-top .container,
+ .navbar-fixed-top .container,
+ .navbar-fixed-bottom .container {
+ width: 1170px;
+ }
+ .span12 {
+ width: 1170px;
+ }
+ .span11 {
+ width: 1070px;
+ }
+ .span10 {
+ width: 970px;
+ }
+ .span9 {
+ width: 870px;
+ }
+ .span8 {
+ width: 770px;
+ }
+ .span7 {
+ width: 670px;
+ }
+ .span6 {
+ width: 570px;
+ }
+ .span5 {
+ width: 470px;
+ }
+ .span4 {
+ width: 370px;
+ }
+ .span3 {
+ width: 270px;
+ }
+ .span2 {
+ width: 170px;
+ }
+ .span1 {
+ width: 70px;
+ }
+ .offset12 {
+ margin-left: 1230px;
+ }
+ .offset11 {
+ margin-left: 1130px;
+ }
+ .offset10 {
+ margin-left: 1030px;
+ }
+ .offset9 {
+ margin-left: 930px;
+ }
+ .offset8 {
+ margin-left: 830px;
+ }
+ .offset7 {
+ margin-left: 730px;
+ }
+ .offset6 {
+ margin-left: 630px;
+ }
+ .offset5 {
+ margin-left: 530px;
+ }
+ .offset4 {
+ margin-left: 430px;
+ }
+ .offset3 {
+ margin-left: 330px;
+ }
+ .offset2 {
+ margin-left: 230px;
+ }
+ .offset1 {
+ margin-left: 130px;
+ }
+ .row-fluid {
+ width: 100%;
+ *zoom: 1;
+ }
+ .row-fluid:before,
+ .row-fluid:after {
+ display: table;
+ line-height: 0;
+ content: "";
+ }
+ .row-fluid:after {
+ clear: both;
+ }
+ .row-fluid [class*="span"] {
+ display: block;
+ float: left;
+ width: 100%;
+ min-height: 30px;
+ margin-left: 2.564102564102564%;
+ *margin-left: 2.5109110747408616%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ }
+ .row-fluid [class*="span"]:first-child {
+ margin-left: 0;
+ }
+ .row-fluid .controls-row [class*="span"] + [class*="span"] {
+ margin-left: 2.564102564102564%;
+ }
+ .row-fluid .span12 {
+ width: 100%;
+ *width: 99.94680851063829%;
+ }
+ .row-fluid .span11 {
+ width: 91.45299145299145%;
+ *width: 91.39979996362975%;
+ }
+ .row-fluid .span10 {
+ width: 82.90598290598291%;
+ *width: 82.8527914166212%;
+ }
+ .row-fluid .span9 {
+ width: 74.35897435897436%;
+ *width: 74.30578286961266%;
+ }
+ .row-fluid .span8 {
+ width: 65.81196581196582%;
+ *width: 65.75877432260411%;
+ }
+ .row-fluid .span7 {
+ width: 57.26495726495726%;
+ *width: 57.21176577559556%;
+ }
+ .row-fluid .span6 {
+ width: 48.717948717948715%;
+ *width: 48.664757228587014%;
+ }
+ .row-fluid .span5 {
+ width: 40.17094017094017%;
+ *width: 40.11774868157847%;
+ }
+ .row-fluid .span4 {
+ width: 31.623931623931625%;
+ *width: 31.570740134569924%;
+ }
+ .row-fluid .span3 {
+ width: 23.076923076923077%;
+ *width: 23.023731587561375%;
+ }
+ .row-fluid .span2 {
+ width: 14.52991452991453%;
+ *width: 14.476723040552828%;
+ }
+ .row-fluid .span1 {
+ width: 5.982905982905983%;
+ *width: 5.929714493544281%;
+ }
+ .row-fluid .offset12 {
+ margin-left: 105.12820512820512%;
+ *margin-left: 105.02182214948171%;
+ }
+ .row-fluid .offset12:first-child {
+ margin-left: 102.56410256410257%;
+ *margin-left: 102.45771958537915%;
+ }
+ .row-fluid .offset11 {
+ margin-left: 96.58119658119658%;
+ *margin-left: 96.47481360247316%;
+ }
+ .row-fluid .offset11:first-child {
+ margin-left: 94.01709401709402%;
+ *margin-left: 93.91071103837061%;
+ }
+ .row-fluid .offset10 {
+ margin-left: 88.03418803418803%;
+ *margin-left: 87.92780505546462%;
+ }
+ .row-fluid .offset10:first-child {
+ margin-left: 85.47008547008548%;
+ *margin-left: 85.36370249136206%;
+ }
+ .row-fluid .offset9 {
+ margin-left: 79.48717948717949%;
+ *margin-left: 79.38079650845607%;
+ }
+ .row-fluid .offset9:first-child {
+ margin-left: 76.92307692307693%;
+ *margin-left: 76.81669394435352%;
+ }
+ .row-fluid .offset8 {
+ margin-left: 70.94017094017094%;
+ *margin-left: 70.83378796144753%;
+ }
+ .row-fluid .offset8:first-child {
+ margin-left: 68.37606837606839%;
+ *margin-left: 68.26968539734497%;
+ }
+ .row-fluid .offset7 {
+ margin-left: 62.393162393162385%;
+ *margin-left: 62.28677941443899%;
+ }
+ .row-fluid .offset7:first-child {
+ margin-left: 59.82905982905982%;
+ *margin-left: 59.72267685033642%;
+ }
+ .row-fluid .offset6 {
+ margin-left: 53.84615384615384%;
+ *margin-left: 53.739770867430444%;
+ }
+ .row-fluid .offset6:first-child {
+ margin-left: 51.28205128205128%;
+ *margin-left: 51.175668303327875%;
+ }
+ .row-fluid .offset5 {
+ margin-left: 45.299145299145295%;
+ *margin-left: 45.1927623204219%;
+ }
+ .row-fluid .offset5:first-child {
+ margin-left: 42.73504273504273%;
+ *margin-left: 42.62865975631933%;
+ }
+ .row-fluid .offset4 {
+ margin-left: 36.75213675213675%;
+ *margin-left: 36.645753773413354%;
+ }
+ .row-fluid .offset4:first-child {
+ margin-left: 34.18803418803419%;
+ *margin-left: 34.081651209310785%;
+ }
+ .row-fluid .offset3 {
+ margin-left: 28.205128205128204%;
+ *margin-left: 28.0987452264048%;
+ }
+ .row-fluid .offset3:first-child {
+ margin-left: 25.641025641025642%;
+ *margin-left: 25.53464266230224%;
+ }
+ .row-fluid .offset2 {
+ margin-left: 19.65811965811966%;
+ *margin-left: 19.551736679396257%;
+ }
+ .row-fluid .offset2:first-child {
+ margin-left: 17.094017094017094%;
+ *margin-left: 16.98763411529369%;
+ }
+ .row-fluid .offset1 {
+ margin-left: 11.11111111111111%;
+ *margin-left: 11.004728132387708%;
+ }
+ .row-fluid .offset1:first-child {
+ margin-left: 8.547008547008547%;
+ *margin-left: 8.440625568285142%;
+ }
+ input,
+ textarea,
+ .uneditable-input {
+ margin-left: 0;
+ }
+ .controls-row [class*="span"] + [class*="span"] {
+ margin-left: 30px;
+ }
+ input.span12,
+ textarea.span12,
+ .uneditable-input.span12 {
+ width: 1156px;
+ }
+ input.span11,
+ textarea.span11,
+ .uneditable-input.span11 {
+ width: 1056px;
+ }
+ input.span10,
+ textarea.span10,
+ .uneditable-input.span10 {
+ width: 956px;
+ }
+ input.span9,
+ textarea.span9,
+ .uneditable-input.span9 {
+ width: 856px;
+ }
+ input.span8,
+ textarea.span8,
+ .uneditable-input.span8 {
+ width: 756px;
+ }
+ input.span7,
+ textarea.span7,
+ .uneditable-input.span7 {
+ width: 656px;
+ }
+ input.span6,
+ textarea.span6,
+ .uneditable-input.span6 {
+ width: 556px;
+ }
+ input.span5,
+ textarea.span5,
+ .uneditable-input.span5 {
+ width: 456px;
+ }
+ input.span4,
+ textarea.span4,
+ .uneditable-input.span4 {
+ width: 356px;
+ }
+ input.span3,
+ textarea.span3,
+ .uneditable-input.span3 {
+ width: 256px;
+ }
+ input.span2,
+ textarea.span2,
+ .uneditable-input.span2 {
+ width: 156px;
+ }
+ input.span1,
+ textarea.span1,
+ .uneditable-input.span1 {
+ width: 56px;
+ }
+ .thumbnails {
+ margin-left: -30px;
+ }
+ .thumbnails > li {
+ margin-left: 30px;
+ }
+ .row-fluid .thumbnails {
+ margin-left: 0;
+ }
+}
+
+@media (min-width: 768px) and (max-width: 979px) {
+ .row {
+ margin-left: -20px;
+ *zoom: 1;
+ }
+ .row:before,
+ .row:after {
+ display: table;
+ line-height: 0;
+ content: "";
+ }
+ .row:after {
+ clear: both;
+ }
+ [class*="span"] {
+ float: left;
+ min-height: 1px;
+ margin-left: 20px;
+ }
+ .container,
+ .navbar-static-top .container,
+ .navbar-fixed-top .container,
+ .navbar-fixed-bottom .container {
+ width: 724px;
+ }
+ .span12 {
+ width: 724px;
+ }
+ .span11 {
+ width: 662px;
+ }
+ .span10 {
+ width: 600px;
+ }
+ .span9 {
+ width: 538px;
+ }
+ .span8 {
+ width: 476px;
+ }
+ .span7 {
+ width: 414px;
+ }
+ .span6 {
+ width: 352px;
+ }
+ .span5 {
+ width: 290px;
+ }
+ .span4 {
+ width: 228px;
+ }
+ .span3 {
+ width: 166px;
+ }
+ .span2 {
+ width: 104px;
+ }
+ .span1 {
+ width: 42px;
+ }
+ .offset12 {
+ margin-left: 764px;
+ }
+ .offset11 {
+ margin-left: 702px;
+ }
+ .offset10 {
+ margin-left: 640px;
+ }
+ .offset9 {
+ margin-left: 578px;
+ }
+ .offset8 {
+ margin-left: 516px;
+ }
+ .offset7 {
+ margin-left: 454px;
+ }
+ .offset6 {
+ margin-left: 392px;
+ }
+ .offset5 {
+ margin-left: 330px;
+ }
+ .offset4 {
+ margin-left: 268px;
+ }
+ .offset3 {
+ margin-left: 206px;
+ }
+ .offset2 {
+ margin-left: 144px;
+ }
+ .offset1 {
+ margin-left: 82px;
+ }
+ .row-fluid {
+ width: 100%;
+ *zoom: 1;
+ }
+ .row-fluid:before,
+ .row-fluid:after {
+ display: table;
+ line-height: 0;
+ content: "";
+ }
+ .row-fluid:after {
+ clear: both;
+ }
+ .row-fluid [class*="span"] {
+ display: block;
+ float: left;
+ width: 100%;
+ min-height: 30px;
+ margin-left: 2.7624309392265194%;
+ *margin-left: 2.709239449864817%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ }
+ .row-fluid [class*="span"]:first-child {
+ margin-left: 0;
+ }
+ .row-fluid .controls-row [class*="span"] + [class*="span"] {
+ margin-left: 2.7624309392265194%;
+ }
+ .row-fluid .span12 {
+ width: 100%;
+ *width: 99.94680851063829%;
+ }
+ .row-fluid .span11 {
+ width: 91.43646408839778%;
+ *width: 91.38327259903608%;
+ }
+ .row-fluid .span10 {
+ width: 82.87292817679558%;
+ *width: 82.81973668743387%;
+ }
+ .row-fluid .span9 {
+ width: 74.30939226519337%;
+ *width: 74.25620077583166%;
+ }
+ .row-fluid .span8 {
+ width: 65.74585635359117%;
+ *width: 65.69266486422946%;
+ }
+ .row-fluid .span7 {
+ width: 57.18232044198895%;
+ *width: 57.12912895262725%;
+ }
+ .row-fluid .span6 {
+ width: 48.61878453038674%;
+ *width: 48.56559304102504%;
+ }
+ .row-fluid .span5 {
+ width: 40.05524861878453%;
+ *width: 40.00205712942283%;
+ }
+ .row-fluid .span4 {
+ width: 31.491712707182323%;
+ *width: 31.43852121782062%;
+ }
+ .row-fluid .span3 {
+ width: 22.92817679558011%;
+ *width: 22.87498530621841%;
+ }
+ .row-fluid .span2 {
+ width: 14.3646408839779%;
+ *width: 14.311449394616199%;
+ }
+ .row-fluid .span1 {
+ width: 5.801104972375691%;
+ *width: 5.747913483013988%;
+ }
+ .row-fluid .offset12 {
+ margin-left: 105.52486187845304%;
+ *margin-left: 105.41847889972962%;
+ }
+ .row-fluid .offset12:first-child {
+ margin-left: 102.76243093922652%;
+ *margin-left: 102.6560479605031%;
+ }
+ .row-fluid .offset11 {
+ margin-left: 96.96132596685082%;
+ *margin-left: 96.8549429881274%;
+ }
+ .row-fluid .offset11:first-child {
+ margin-left: 94.1988950276243%;
+ *margin-left: 94.09251204890089%;
+ }
+ .row-fluid .offset10 {
+ margin-left: 88.39779005524862%;
+ *margin-left: 88.2914070765252%;
+ }
+ .row-fluid .offset10:first-child {
+ margin-left: 85.6353591160221%;
+ *margin-left: 85.52897613729868%;
+ }
+ .row-fluid .offset9 {
+ margin-left: 79.8342541436464%;
+ *margin-left: 79.72787116492299%;
+ }
+ .row-fluid .offset9:first-child {
+ margin-left: 77.07182320441989%;
+ *margin-left: 76.96544022569647%;
+ }
+ .row-fluid .offset8 {
+ margin-left: 71.2707182320442%;
+ *margin-left: 71.16433525332079%;
+ }
+ .row-fluid .offset8:first-child {
+ margin-left: 68.50828729281768%;
+ *margin-left: 68.40190431409427%;
+ }
+ .row-fluid .offset7 {
+ margin-left: 62.70718232044199%;
+ *margin-left: 62.600799341718584%;
+ }
+ .row-fluid .offset7:first-child {
+ margin-left: 59.94475138121547%;
+ *margin-left: 59.838368402492065%;
+ }
+ .row-fluid .offset6 {
+ margin-left: 54.14364640883978%;
+ *margin-left: 54.037263430116376%;
+ }
+ .row-fluid .offset6:first-child {
+ margin-left: 51.38121546961326%;
+ *margin-left: 51.27483249088986%;
+ }
+ .row-fluid .offset5 {
+ margin-left: 45.58011049723757%;
+ *margin-left: 45.47372751851417%;
+ }
+ .row-fluid .offset5:first-child {
+ margin-left: 42.81767955801105%;
+ *margin-left: 42.71129657928765%;
+ }
+ .row-fluid .offset4 {
+ margin-left: 37.01657458563536%;
+ *margin-left: 36.91019160691196%;
+ }
+ .row-fluid .offset4:first-child {
+ margin-left: 34.25414364640884%;
+ *margin-left: 34.14776066768544%;
+ }
+ .row-fluid .offset3 {
+ margin-left: 28.45303867403315%;
+ *margin-left: 28.346655695309746%;
+ }
+ .row-fluid .offset3:first-child {
+ margin-left: 25.69060773480663%;
+ *margin-left: 25.584224756083227%;
+ }
+ .row-fluid .offset2 {
+ margin-left: 19.88950276243094%;
+ *margin-left: 19.783119783707537%;
+ }
+ .row-fluid .offset2:first-child {
+ margin-left: 17.12707182320442%;
+ *margin-left: 17.02068884448102%;
+ }
+ .row-fluid .offset1 {
+ margin-left: 11.32596685082873%;
+ *margin-left: 11.219583872105325%;
+ }
+ .row-fluid .offset1:first-child {
+ margin-left: 8.56353591160221%;
+ *margin-left: 8.457152932878806%;
+ }
+ input,
+ textarea,
+ .uneditable-input {
+ margin-left: 0;
+ }
+ .controls-row [class*="span"] + [class*="span"] {
+ margin-left: 20px;
+ }
+ input.span12,
+ textarea.span12,
+ .uneditable-input.span12 {
+ width: 710px;
+ }
+ input.span11,
+ textarea.span11,
+ .uneditable-input.span11 {
+ width: 648px;
+ }
+ input.span10,
+ textarea.span10,
+ .uneditable-input.span10 {
+ width: 586px;
+ }
+ input.span9,
+ textarea.span9,
+ .uneditable-input.span9 {
+ width: 524px;
+ }
+ input.span8,
+ textarea.span8,
+ .uneditable-input.span8 {
+ width: 462px;
+ }
+ input.span7,
+ textarea.span7,
+ .uneditable-input.span7 {
+ width: 400px;
+ }
+ input.span6,
+ textarea.span6,
+ .uneditable-input.span6 {
+ width: 338px;
+ }
+ input.span5,
+ textarea.span5,
+ .uneditable-input.span5 {
+ width: 276px;
+ }
+ input.span4,
+ textarea.span4,
+ .uneditable-input.span4 {
+ width: 214px;
+ }
+ input.span3,
+ textarea.span3,
+ .uneditable-input.span3 {
+ width: 152px;
+ }
+ input.span2,
+ textarea.span2,
+ .uneditable-input.span2 {
+ width: 90px;
+ }
+ input.span1,
+ textarea.span1,
+ .uneditable-input.span1 {
+ width: 28px;
+ }
+}
+
+@media (max-width: 767px) {
+ body {
+ padding-right: 20px;
+ padding-left: 20px;
+ }
+ .navbar-fixed-top,
+ .navbar-fixed-bottom,
+ .navbar-static-top {
+ margin-right: -20px;
+ margin-left: -20px;
+ }
+ .container-fluid {
+ padding: 0;
+ }
+ .dl-horizontal dt {
+ float: none;
+ width: auto;
+ clear: none;
+ text-align: left;
+ }
+ .dl-horizontal dd {
+ margin-left: 0;
+ }
+ .container {
+ width: auto;
+ }
+ .row-fluid {
+ width: 100%;
+ }
+ .row,
+ .thumbnails {
+ margin-left: 0;
+ }
+ .thumbnails > li {
+ float: none;
+ margin-left: 0;
+ }
+ [class*="span"],
+ .uneditable-input[class*="span"],
+ .row-fluid [class*="span"] {
+ display: block;
+ float: none;
+ width: 100%;
+ margin-left: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ }
+ .span12,
+ .row-fluid .span12 {
+ width: 100%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ }
+ .row-fluid [class*="offset"]:first-child {
+ margin-left: 0;
+ }
+ .input-large,
+ .input-xlarge,
+ .input-xxlarge,
+ input[class*="span"],
+ select[class*="span"],
+ textarea[class*="span"],
+ .uneditable-input {
+ display: block;
+ width: 100%;
+ min-height: 30px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ }
+ .input-prepend input,
+ .input-append input,
+ .input-prepend input[class*="span"],
+ .input-append input[class*="span"] {
+ display: inline-block;
+ width: auto;
+ }
+ .controls-row [class*="span"] + [class*="span"] {
+ margin-left: 0;
+ }
+ .modal {
+ position: fixed;
+ top: 20px;
+ right: 20px;
+ left: 20px;
+ width: auto;
+ margin: 0;
+ }
+ .modal.fade {
+ top: -100px;
+ }
+ .modal.fade.in {
+ top: 20px;
+ }
+}
+
+@media (max-width: 480px) {
+ .nav-collapse {
+ -webkit-transform: translate3d(0, 0, 0);
+ }
+ .page-header h1 small {
+ display: block;
+ line-height: 20px;
+ }
+ input[type="checkbox"],
+ input[type="radio"] {
+ border: 1px solid #ccc;
+ }
+ .form-horizontal .control-label {
+ float: none;
+ width: auto;
+ padding-top: 0;
+ text-align: left;
+ }
+ .form-horizontal .controls {
+ margin-left: 0;
+ }
+ .form-horizontal .control-list {
+ padding-top: 0;
+ }
+ .form-horizontal .form-actions {
+ padding-right: 10px;
+ padding-left: 10px;
+ }
+ .media .pull-left,
+ .media .pull-right {
+ display: block;
+ float: none;
+ margin-bottom: 10px;
+ }
+ .media-object {
+ margin-right: 0;
+ margin-left: 0;
+ }
+ .modal {
+ top: 10px;
+ right: 10px;
+ left: 10px;
+ }
+ .modal-header .close {
+ padding: 10px;
+ margin: -10px;
+ }
+ .carousel-caption {
+ position: static;
+ }
+}
+
+@media (max-width: 979px) {
+ body {
+ padding-top: 0;
+ }
+ .navbar-fixed-top,
+ .navbar-fixed-bottom {
+ position: static;
+ }
+ .navbar-fixed-top {
+ margin-bottom: 20px;
+ }
+ .navbar-fixed-bottom {
+ margin-top: 20px;
+ }
+ .navbar-fixed-top .navbar-inner,
+ .navbar-fixed-bottom .navbar-inner {
+ padding: 5px;
+ }
+ .navbar .container {
+ width: auto;
+ padding: 0;
+ }
+ .navbar .brand {
+ padding-right: 10px;
+ padding-left: 10px;
+ margin: 0 0 0 -5px;
+ }
+ .nav-collapse {
+ clear: both;
+ }
+ .nav-collapse .nav {
+ float: none;
+ margin: 0 0 10px;
+ }
+ .nav-collapse .nav > li {
+ float: none;
+ }
+ .nav-collapse .nav > li > a {
+ margin-bottom: 2px;
+ }
+ .nav-collapse .nav > .divider-vertical {
+ display: none;
+ }
+ .nav-collapse .nav .nav-header {
+ color: #777777;
+ text-shadow: none;
+ }
+ .nav-collapse .nav > li > a,
+ .nav-collapse .dropdown-menu a {
+ padding: 9px 15px;
+ font-weight: bold;
+ color: #777777;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+ }
+ .nav-collapse .btn {
+ padding: 4px 10px 4px;
+ font-weight: normal;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ }
+ .nav-collapse .dropdown-menu li + li a {
+ margin-bottom: 2px;
+ }
+ .nav-collapse .nav > li > a:hover,
+ .nav-collapse .nav > li > a:focus,
+ .nav-collapse .dropdown-menu a:hover,
+ .nav-collapse .dropdown-menu a:focus {
+ background-color: #f2f2f2;
+ }
+ .navbar-inverse .nav-collapse .nav > li > a,
+ .navbar-inverse .nav-collapse .dropdown-menu a {
+ color: #999999;
+ }
+ .navbar-inverse .nav-collapse .nav > li > a:hover,
+ .navbar-inverse .nav-collapse .nav > li > a:focus,
+ .navbar-inverse .nav-collapse .dropdown-menu a:hover,
+ .navbar-inverse .nav-collapse .dropdown-menu a:focus {
+ background-color: #111111;
+ }
+ .nav-collapse.in .btn-group {
+ padding: 0;
+ margin-top: 5px;
+ }
+ .nav-collapse .dropdown-menu {
+ position: static;
+ top: auto;
+ left: auto;
+ display: none;
+ float: none;
+ max-width: none;
+ padding: 0;
+ margin: 0 15px;
+ background-color: transparent;
+ border: none;
+ -webkit-border-radius: 0;
+ -moz-border-radius: 0;
+ border-radius: 0;
+ -webkit-box-shadow: none;
+ -moz-box-shadow: none;
+ box-shadow: none;
+ }
+ .nav-collapse .open > .dropdown-menu {
+ display: block;
+ }
+ .nav-collapse .dropdown-menu:before,
+ .nav-collapse .dropdown-menu:after {
+ display: none;
+ }
+ .nav-collapse .dropdown-menu .divider {
+ display: none;
+ }
+ .nav-collapse .nav > li > .dropdown-menu:before,
+ .nav-collapse .nav > li > .dropdown-menu:after {
+ display: none;
+ }
+ .nav-collapse .navbar-form,
+ .nav-collapse .navbar-search {
+ float: none;
+ padding: 10px 15px;
+ margin: 10px 0;
+ border-top: 1px solid #f2f2f2;
+ border-bottom: 1px solid #f2f2f2;
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+ }
+ .navbar-inverse .nav-collapse .navbar-form,
+ .navbar-inverse .nav-collapse .navbar-search {
+ border-top-color: #111111;
+ border-bottom-color: #111111;
+ }
+ .navbar .nav-collapse .nav.pull-right {
+ float: none;
+ margin-left: 0;
+ }
+ .nav-collapse,
+ .nav-collapse.collapse {
+ height: 0;
+ overflow: hidden;
+ }
+ .navbar .btn-navbar {
+ display: block;
+ }
+ .navbar-static .navbar-inner {
+ padding-right: 10px;
+ padding-left: 10px;
+ }
+}
+
+@media (min-width: 980px) {
+ .nav-collapse.collapse {
+ height: auto !important;
+ overflow: visible !important;
+ }
+}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap-responsive.min.css b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap-responsive.min.css
new file mode 100644
index 0000000..d1b7f4b
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/css/bootstrap-responsive.min.css
@@ -0,0 +1,9 @@
+/*!
+ * Bootstrap Responsive v2.3.1
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}@-ms-viewport{width:device-width}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:inherit!important}.hidden-print{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .nav>li>a:focus,.nav-collapse .dropdown-menu a:hover,.nav-collapse .dropdown-menu a:focus{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .nav>li>a:focus,.navbar-inverse .nav-collapse .dropdown-menu a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:focus{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}}
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/add_B.gif b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/add_B.gif
new file mode 100644
index 0000000..b8aed96
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/add_B.gif differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/best_sellers.gif b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/best_sellers.gif
new file mode 100644
index 0000000..25dc936
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/best_sellers.gif differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/checkout_B.gif b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/checkout_B.gif
new file mode 100644
index 0000000..fd793e6
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/checkout_B.gif differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/display_last_order_B.gif b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/display_last_order_B.gif
new file mode 100644
index 0000000..569cb83
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/display_last_order_B.gif differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/glyphicons-halflings.png b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/glyphicons-halflings.png
new file mode 100644
index 0000000..a996999
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/glyphicons-halflings.png differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/glyphicons-halflings-white.png b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/glyphicons-halflings-white.png
new file mode 100644
index 0000000..3bf6484
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/glyphicons-halflings-white.png differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/home_B.gif b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/home_B.gif
new file mode 100644
index 0000000..972c356
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/home_B.gif differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/logo-CloudScale.png b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/logo-CloudScale.png
new file mode 100644
index 0000000..3500f6c
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/logo-CloudScale.png differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/logo-CloudScale-aws.png b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/logo-CloudScale-aws.png
new file mode 100644
index 0000000..069cadd
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/logo-CloudScale-aws.png differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/order_status_B.gif b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/order_status_B.gif
new file mode 100644
index 0000000..91c3ffc
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/order_status_B.gif differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/refresh_B.gif b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/refresh_B.gif
new file mode 100644
index 0000000..944aab6
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/refresh_B.gif differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/search_B.gif b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/search_B.gif
new file mode 100644
index 0000000..b2f115e
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/search_B.gif differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/shopping_cart_B.gif b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/shopping_cart_B.gif
new file mode 100644
index 0000000..d68076f
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/shopping_cart_B.gif differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/submit_B.gif b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/submit_B.gif
new file mode 100644
index 0000000..a3e3b71
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/submit_B.gif differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/tpclogo.gif b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/tpclogo.gif
new file mode 100644
index 0000000..f0fde9d
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/tpclogo.gif differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/update_B.gif b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/update_B.gif
new file mode 100644
index 0000000..584a852
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/update_B.gif differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/whats_new.gif b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/whats_new.gif
new file mode 100644
index 0000000..892c02a
Binary files /dev/null and b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/img/whats_new.gif differ
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/js/bootstrap.js b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/js/bootstrap.js
new file mode 100644
index 0000000..c298ee4
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/js/bootstrap.js
@@ -0,0 +1,2276 @@
+/* ===================================================
+ * bootstrap-transition.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#transitions
+ * ===================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* CSS TRANSITION SUPPORT (http://www.modernizr.com/)
+ * ======================================================= */
+
+ $(function () {
+
+ $.support.transition = (function () {
+
+ var transitionEnd = (function () {
+
+ var el = document.createElement('bootstrap')
+ , transEndEventNames = {
+ 'WebkitTransition' : 'webkitTransitionEnd'
+ , 'MozTransition' : 'transitionend'
+ , 'OTransition' : 'oTransitionEnd otransitionend'
+ , 'transition' : 'transitionend'
+ }
+ , name
+
+ for (name in transEndEventNames){
+ if (el.style[name] !== undefined) {
+ return transEndEventNames[name]
+ }
+ }
+
+ }())
+
+ return transitionEnd && {
+ end: transitionEnd
+ }
+
+ })()
+
+ })
+
+}(window.jQuery);/* ==========================================================
+ * bootstrap-alert.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#alerts
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* ALERT CLASS DEFINITION
+ * ====================== */
+
+ var dismiss = '[data-dismiss="alert"]'
+ , Alert = function (el) {
+ $(el).on('click', dismiss, this.close)
+ }
+
+ Alert.prototype.close = function (e) {
+ var $this = $(this)
+ , selector = $this.attr('data-target')
+ , $parent
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+ }
+
+ $parent = $(selector)
+
+ e && e.preventDefault()
+
+ $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
+
+ $parent.trigger(e = $.Event('close'))
+
+ if (e.isDefaultPrevented()) return
+
+ $parent.removeClass('in')
+
+ function removeElement() {
+ $parent
+ .trigger('closed')
+ .remove()
+ }
+
+ $.support.transition && $parent.hasClass('fade') ?
+ $parent.on($.support.transition.end, removeElement) :
+ removeElement()
+ }
+
+
+ /* ALERT PLUGIN DEFINITION
+ * ======================= */
+
+ var old = $.fn.alert
+
+ $.fn.alert = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('alert')
+ if (!data) $this.data('alert', (data = new Alert(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ $.fn.alert.Constructor = Alert
+
+
+ /* ALERT NO CONFLICT
+ * ================= */
+
+ $.fn.alert.noConflict = function () {
+ $.fn.alert = old
+ return this
+ }
+
+
+ /* ALERT DATA-API
+ * ============== */
+
+ $(document).on('click.alert.data-api', dismiss, Alert.prototype.close)
+
+}(window.jQuery);/* ============================================================
+ * bootstrap-button.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#buttons
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* BUTTON PUBLIC CLASS DEFINITION
+ * ============================== */
+
+ var Button = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.button.defaults, options)
+ }
+
+ Button.prototype.setState = function (state) {
+ var d = 'disabled'
+ , $el = this.$element
+ , data = $el.data()
+ , val = $el.is('input') ? 'val' : 'html'
+
+ state = state + 'Text'
+ data.resetText || $el.data('resetText', $el[val]())
+
+ $el[val](data[state] || this.options[state])
+
+ // push to event loop to allow forms to submit
+ setTimeout(function () {
+ state == 'loadingText' ?
+ $el.addClass(d).attr(d, d) :
+ $el.removeClass(d).removeAttr(d)
+ }, 0)
+ }
+
+ Button.prototype.toggle = function () {
+ var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
+
+ $parent && $parent
+ .find('.active')
+ .removeClass('active')
+
+ this.$element.toggleClass('active')
+ }
+
+
+ /* BUTTON PLUGIN DEFINITION
+ * ======================== */
+
+ var old = $.fn.button
+
+ $.fn.button = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('button')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('button', (data = new Button(this, options)))
+ if (option == 'toggle') data.toggle()
+ else if (option) data.setState(option)
+ })
+ }
+
+ $.fn.button.defaults = {
+ loadingText: 'loading...'
+ }
+
+ $.fn.button.Constructor = Button
+
+
+ /* BUTTON NO CONFLICT
+ * ================== */
+
+ $.fn.button.noConflict = function () {
+ $.fn.button = old
+ return this
+ }
+
+
+ /* BUTTON DATA-API
+ * =============== */
+
+ $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) {
+ var $btn = $(e.target)
+ if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+ $btn.button('toggle')
+ })
+
+}(window.jQuery);/* ==========================================================
+ * bootstrap-carousel.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#carousel
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* CAROUSEL CLASS DEFINITION
+ * ========================= */
+
+ var Carousel = function (element, options) {
+ this.$element = $(element)
+ this.$indicators = this.$element.find('.carousel-indicators')
+ this.options = options
+ this.options.pause == 'hover' && this.$element
+ .on('mouseenter', $.proxy(this.pause, this))
+ .on('mouseleave', $.proxy(this.cycle, this))
+ }
+
+ Carousel.prototype = {
+
+ cycle: function (e) {
+ if (!e) this.paused = false
+ if (this.interval) clearInterval(this.interval);
+ this.options.interval
+ && !this.paused
+ && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+ return this
+ }
+
+ , getActiveIndex: function () {
+ this.$active = this.$element.find('.item.active')
+ this.$items = this.$active.parent().children()
+ return this.$items.index(this.$active)
+ }
+
+ , to: function (pos) {
+ var activeIndex = this.getActiveIndex()
+ , that = this
+
+ if (pos > (this.$items.length - 1) || pos < 0) return
+
+ if (this.sliding) {
+ return this.$element.one('slid', function () {
+ that.to(pos)
+ })
+ }
+
+ if (activeIndex == pos) {
+ return this.pause().cycle()
+ }
+
+ return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
+ }
+
+ , pause: function (e) {
+ if (!e) this.paused = true
+ if (this.$element.find('.next, .prev').length && $.support.transition.end) {
+ this.$element.trigger($.support.transition.end)
+ this.cycle(true)
+ }
+ clearInterval(this.interval)
+ this.interval = null
+ return this
+ }
+
+ , next: function () {
+ if (this.sliding) return
+ return this.slide('next')
+ }
+
+ , prev: function () {
+ if (this.sliding) return
+ return this.slide('prev')
+ }
+
+ , slide: function (type, next) {
+ var $active = this.$element.find('.item.active')
+ , $next = next || $active[type]()
+ , isCycling = this.interval
+ , direction = type == 'next' ? 'left' : 'right'
+ , fallback = type == 'next' ? 'first' : 'last'
+ , that = this
+ , e
+
+ this.sliding = true
+
+ isCycling && this.pause()
+
+ $next = $next.length ? $next : this.$element.find('.item')[fallback]()
+
+ e = $.Event('slide', {
+ relatedTarget: $next[0]
+ , direction: direction
+ })
+
+ if ($next.hasClass('active')) return
+
+ if (this.$indicators.length) {
+ this.$indicators.find('.active').removeClass('active')
+ this.$element.one('slid', function () {
+ var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])
+ $nextIndicator && $nextIndicator.addClass('active')
+ })
+ }
+
+ if ($.support.transition && this.$element.hasClass('slide')) {
+ this.$element.trigger(e)
+ if (e.isDefaultPrevented()) return
+ $next.addClass(type)
+ $next[0].offsetWidth // force reflow
+ $active.addClass(direction)
+ $next.addClass(direction)
+ this.$element.one($.support.transition.end, function () {
+ $next.removeClass([type, direction].join(' ')).addClass('active')
+ $active.removeClass(['active', direction].join(' '))
+ that.sliding = false
+ setTimeout(function () { that.$element.trigger('slid') }, 0)
+ })
+ } else {
+ this.$element.trigger(e)
+ if (e.isDefaultPrevented()) return
+ $active.removeClass('active')
+ $next.addClass('active')
+ this.sliding = false
+ this.$element.trigger('slid')
+ }
+
+ isCycling && this.cycle()
+
+ return this
+ }
+
+ }
+
+
+ /* CAROUSEL PLUGIN DEFINITION
+ * ========================== */
+
+ var old = $.fn.carousel
+
+ $.fn.carousel = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('carousel')
+ , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option)
+ , action = typeof option == 'string' ? option : options.slide
+ if (!data) $this.data('carousel', (data = new Carousel(this, options)))
+ if (typeof option == 'number') data.to(option)
+ else if (action) data[action]()
+ else if (options.interval) data.pause().cycle()
+ })
+ }
+
+ $.fn.carousel.defaults = {
+ interval: 5000
+ , pause: 'hover'
+ }
+
+ $.fn.carousel.Constructor = Carousel
+
+
+ /* CAROUSEL NO CONFLICT
+ * ==================== */
+
+ $.fn.carousel.noConflict = function () {
+ $.fn.carousel = old
+ return this
+ }
+
+ /* CAROUSEL DATA-API
+ * ================= */
+
+ $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
+ var $this = $(this), href
+ , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+ , options = $.extend({}, $target.data(), $this.data())
+ , slideIndex
+
+ $target.carousel(options)
+
+ if (slideIndex = $this.attr('data-slide-to')) {
+ $target.data('carousel').pause().to(slideIndex).cycle()
+ }
+
+ e.preventDefault()
+ })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-collapse.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#collapse
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* COLLAPSE PUBLIC CLASS DEFINITION
+ * ================================ */
+
+ var Collapse = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.collapse.defaults, options)
+
+ if (this.options.parent) {
+ this.$parent = $(this.options.parent)
+ }
+
+ this.options.toggle && this.toggle()
+ }
+
+ Collapse.prototype = {
+
+ constructor: Collapse
+
+ , dimension: function () {
+ var hasWidth = this.$element.hasClass('width')
+ return hasWidth ? 'width' : 'height'
+ }
+
+ , show: function () {
+ var dimension
+ , scroll
+ , actives
+ , hasData
+
+ if (this.transitioning || this.$element.hasClass('in')) return
+
+ dimension = this.dimension()
+ scroll = $.camelCase(['scroll', dimension].join('-'))
+ actives = this.$parent && this.$parent.find('> .accordion-group > .in')
+
+ if (actives && actives.length) {
+ hasData = actives.data('collapse')
+ if (hasData && hasData.transitioning) return
+ actives.collapse('hide')
+ hasData || actives.data('collapse', null)
+ }
+
+ this.$element[dimension](0)
+ this.transition('addClass', $.Event('show'), 'shown')
+ $.support.transition && this.$element[dimension](this.$element[0][scroll])
+ }
+
+ , hide: function () {
+ var dimension
+ if (this.transitioning || !this.$element.hasClass('in')) return
+ dimension = this.dimension()
+ this.reset(this.$element[dimension]())
+ this.transition('removeClass', $.Event('hide'), 'hidden')
+ this.$element[dimension](0)
+ }
+
+ , reset: function (size) {
+ var dimension = this.dimension()
+
+ this.$element
+ .removeClass('collapse')
+ [dimension](size || 'auto')
+ [0].offsetWidth
+
+ this.$element[size !== null ? 'addClass' : 'removeClass']('collapse')
+
+ return this
+ }
+
+ , transition: function (method, startEvent, completeEvent) {
+ var that = this
+ , complete = function () {
+ if (startEvent.type == 'show') that.reset()
+ that.transitioning = 0
+ that.$element.trigger(completeEvent)
+ }
+
+ this.$element.trigger(startEvent)
+
+ if (startEvent.isDefaultPrevented()) return
+
+ this.transitioning = 1
+
+ this.$element[method]('in')
+
+ $.support.transition && this.$element.hasClass('collapse') ?
+ this.$element.one($.support.transition.end, complete) :
+ complete()
+ }
+
+ , toggle: function () {
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
+ }
+
+ }
+
+
+ /* COLLAPSE PLUGIN DEFINITION
+ * ========================== */
+
+ var old = $.fn.collapse
+
+ $.fn.collapse = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('collapse')
+ , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option)
+ if (!data) $this.data('collapse', (data = new Collapse(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.collapse.defaults = {
+ toggle: true
+ }
+
+ $.fn.collapse.Constructor = Collapse
+
+
+ /* COLLAPSE NO CONFLICT
+ * ==================== */
+
+ $.fn.collapse.noConflict = function () {
+ $.fn.collapse = old
+ return this
+ }
+
+
+ /* COLLAPSE DATA-API
+ * ================= */
+
+ $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
+ var $this = $(this), href
+ , target = $this.attr('data-target')
+ || e.preventDefault()
+ || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
+ , option = $(target).data('collapse') ? 'toggle' : $this.data()
+ $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
+ $(target).collapse(option)
+ })
+
+}(window.jQuery);/* ============================================================
+ * bootstrap-dropdown.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#dropdowns
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* DROPDOWN CLASS DEFINITION
+ * ========================= */
+
+ var toggle = '[data-toggle=dropdown]'
+ , Dropdown = function (element) {
+ var $el = $(element).on('click.dropdown.data-api', this.toggle)
+ $('html').on('click.dropdown.data-api', function () {
+ $el.parent().removeClass('open')
+ })
+ }
+
+ Dropdown.prototype = {
+
+ constructor: Dropdown
+
+ , toggle: function (e) {
+ var $this = $(this)
+ , $parent
+ , isActive
+
+ if ($this.is('.disabled, :disabled')) return
+
+ $parent = getParent($this)
+
+ isActive = $parent.hasClass('open')
+
+ clearMenus()
+
+ if (!isActive) {
+ $parent.toggleClass('open')
+ }
+
+ $this.focus()
+
+ return false
+ }
+
+ , keydown: function (e) {
+ var $this
+ , $items
+ , $active
+ , $parent
+ , isActive
+ , index
+
+ if (!/(38|40|27)/.test(e.keyCode)) return
+
+ $this = $(this)
+
+ e.preventDefault()
+ e.stopPropagation()
+
+ if ($this.is('.disabled, :disabled')) return
+
+ $parent = getParent($this)
+
+ isActive = $parent.hasClass('open')
+
+ if (!isActive || (isActive && e.keyCode == 27)) {
+ if (e.which == 27) $parent.find(toggle).focus()
+ return $this.click()
+ }
+
+ $items = $('[role=menu] li:not(.divider):visible a', $parent)
+
+ if (!$items.length) return
+
+ index = $items.index($items.filter(':focus'))
+
+ if (e.keyCode == 38 && index > 0) index-- // up
+ if (e.keyCode == 40 && index < $items.length - 1) index++ // down
+ if (!~index) index = 0
+
+ $items
+ .eq(index)
+ .focus()
+ }
+
+ }
+
+ function clearMenus() {
+ $(toggle).each(function () {
+ getParent($(this)).removeClass('open')
+ })
+ }
+
+ function getParent($this) {
+ var selector = $this.attr('data-target')
+ , $parent
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+ }
+
+ $parent = selector && $(selector)
+
+ if (!$parent || !$parent.length) $parent = $this.parent()
+
+ return $parent
+ }
+
+
+ /* DROPDOWN PLUGIN DEFINITION
+ * ========================== */
+
+ var old = $.fn.dropdown
+
+ $.fn.dropdown = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('dropdown')
+ if (!data) $this.data('dropdown', (data = new Dropdown(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ $.fn.dropdown.Constructor = Dropdown
+
+
+ /* DROPDOWN NO CONFLICT
+ * ==================== */
+
+ $.fn.dropdown.noConflict = function () {
+ $.fn.dropdown = old
+ return this
+ }
+
+
+ /* APPLY TO STANDARD DROPDOWN ELEMENTS
+ * =================================== */
+
+ $(document)
+ .on('click.dropdown.data-api', clearMenus)
+ .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
+ .on('click.dropdown-menu', function (e) { e.stopPropagation() })
+ .on('click.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
+ .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
+
+}(window.jQuery);
+/* =========================================================
+ * bootstrap-modal.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#modals
+ * =========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* MODAL CLASS DEFINITION
+ * ====================== */
+
+ var Modal = function (element, options) {
+ this.options = options
+ this.$element = $(element)
+ .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
+ this.options.remote && this.$element.find('.modal-body').load(this.options.remote)
+ }
+
+ Modal.prototype = {
+
+ constructor: Modal
+
+ , toggle: function () {
+ return this[!this.isShown ? 'show' : 'hide']()
+ }
+
+ , show: function () {
+ var that = this
+ , e = $.Event('show')
+
+ this.$element.trigger(e)
+
+ if (this.isShown || e.isDefaultPrevented()) return
+
+ this.isShown = true
+
+ this.escape()
+
+ this.backdrop(function () {
+ var transition = $.support.transition && that.$element.hasClass('fade')
+
+ if (!that.$element.parent().length) {
+ that.$element.appendTo(document.body) //don't move modals dom position
+ }
+
+ that.$element.show()
+
+ if (transition) {
+ that.$element[0].offsetWidth // force reflow
+ }
+
+ that.$element
+ .addClass('in')
+ .attr('aria-hidden', false)
+
+ that.enforceFocus()
+
+ transition ?
+ that.$element.one($.support.transition.end, function () { that.$element.focus().trigger('shown') }) :
+ that.$element.focus().trigger('shown')
+
+ })
+ }
+
+ , hide: function (e) {
+ e && e.preventDefault()
+
+ var that = this
+
+ e = $.Event('hide')
+
+ this.$element.trigger(e)
+
+ if (!this.isShown || e.isDefaultPrevented()) return
+
+ this.isShown = false
+
+ this.escape()
+
+ $(document).off('focusin.modal')
+
+ this.$element
+ .removeClass('in')
+ .attr('aria-hidden', true)
+
+ $.support.transition && this.$element.hasClass('fade') ?
+ this.hideWithTransition() :
+ this.hideModal()
+ }
+
+ , enforceFocus: function () {
+ var that = this
+ $(document).on('focusin.modal', function (e) {
+ if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
+ that.$element.focus()
+ }
+ })
+ }
+
+ , escape: function () {
+ var that = this
+ if (this.isShown && this.options.keyboard) {
+ this.$element.on('keyup.dismiss.modal', function ( e ) {
+ e.which == 27 && that.hide()
+ })
+ } else if (!this.isShown) {
+ this.$element.off('keyup.dismiss.modal')
+ }
+ }
+
+ , hideWithTransition: function () {
+ var that = this
+ , timeout = setTimeout(function () {
+ that.$element.off($.support.transition.end)
+ that.hideModal()
+ }, 500)
+
+ this.$element.one($.support.transition.end, function () {
+ clearTimeout(timeout)
+ that.hideModal()
+ })
+ }
+
+ , hideModal: function () {
+ var that = this
+ this.$element.hide()
+ this.backdrop(function () {
+ that.removeBackdrop()
+ that.$element.trigger('hidden')
+ })
+ }
+
+ , removeBackdrop: function () {
+ this.$backdrop && this.$backdrop.remove()
+ this.$backdrop = null
+ }
+
+ , backdrop: function (callback) {
+ var that = this
+ , animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+ if (this.isShown && this.options.backdrop) {
+ var doAnimate = $.support.transition && animate
+
+ this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
+ .appendTo(document.body)
+
+ this.$backdrop.click(
+ this.options.backdrop == 'static' ?
+ $.proxy(this.$element[0].focus, this.$element[0])
+ : $.proxy(this.hide, this)
+ )
+
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+ this.$backdrop.addClass('in')
+
+ if (!callback) return
+
+ doAnimate ?
+ this.$backdrop.one($.support.transition.end, callback) :
+ callback()
+
+ } else if (!this.isShown && this.$backdrop) {
+ this.$backdrop.removeClass('in')
+
+ $.support.transition && this.$element.hasClass('fade')?
+ this.$backdrop.one($.support.transition.end, callback) :
+ callback()
+
+ } else if (callback) {
+ callback()
+ }
+ }
+ }
+
+
+ /* MODAL PLUGIN DEFINITION
+ * ======================= */
+
+ var old = $.fn.modal
+
+ $.fn.modal = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('modal')
+ , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
+ if (!data) $this.data('modal', (data = new Modal(this, options)))
+ if (typeof option == 'string') data[option]()
+ else if (options.show) data.show()
+ })
+ }
+
+ $.fn.modal.defaults = {
+ backdrop: true
+ , keyboard: true
+ , show: true
+ }
+
+ $.fn.modal.Constructor = Modal
+
+
+ /* MODAL NO CONFLICT
+ * ================= */
+
+ $.fn.modal.noConflict = function () {
+ $.fn.modal = old
+ return this
+ }
+
+
+ /* MODAL DATA-API
+ * ============== */
+
+ $(document).on('click.modal.data-api', '[data-toggle="modal"]', function (e) {
+ var $this = $(this)
+ , href = $this.attr('href')
+ , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
+ , option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())
+
+ e.preventDefault()
+
+ $target
+ .modal(option)
+ .one('hide', function () {
+ $this.focus()
+ })
+ })
+
+}(window.jQuery);
+/* ===========================================================
+ * bootstrap-tooltip.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#tooltips
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* TOOLTIP PUBLIC CLASS DEFINITION
+ * =============================== */
+
+ var Tooltip = function (element, options) {
+ this.init('tooltip', element, options)
+ }
+
+ Tooltip.prototype = {
+
+ constructor: Tooltip
+
+ , init: function (type, element, options) {
+ var eventIn
+ , eventOut
+ , triggers
+ , trigger
+ , i
+
+ this.type = type
+ this.$element = $(element)
+ this.options = this.getOptions(options)
+ this.enabled = true
+
+ triggers = this.options.trigger.split(' ')
+
+ for (i = triggers.length; i--;) {
+ trigger = triggers[i]
+ if (trigger == 'click') {
+ this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+ } else if (trigger != 'manual') {
+ eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
+ eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
+ this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+ this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+ }
+ }
+
+ this.options.selector ?
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+ this.fixTitle()
+ }
+
+ , getOptions: function (options) {
+ options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options)
+
+ if (options.delay && typeof options.delay == 'number') {
+ options.delay = {
+ show: options.delay
+ , hide: options.delay
+ }
+ }
+
+ return options
+ }
+
+ , enter: function (e) {
+ var defaults = $.fn[this.type].defaults
+ , options = {}
+ , self
+
+ this._options && $.each(this._options, function (key, value) {
+ if (defaults[key] != value) options[key] = value
+ }, this)
+
+ self = $(e.currentTarget)[this.type](options).data(this.type)
+
+ if (!self.options.delay || !self.options.delay.show) return self.show()
+
+ clearTimeout(this.timeout)
+ self.hoverState = 'in'
+ this.timeout = setTimeout(function() {
+ if (self.hoverState == 'in') self.show()
+ }, self.options.delay.show)
+ }
+
+ , leave: function (e) {
+ var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+ if (this.timeout) clearTimeout(this.timeout)
+ if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+ self.hoverState = 'out'
+ this.timeout = setTimeout(function() {
+ if (self.hoverState == 'out') self.hide()
+ }, self.options.delay.hide)
+ }
+
+ , show: function () {
+ var $tip
+ , pos
+ , actualWidth
+ , actualHeight
+ , placement
+ , tp
+ , e = $.Event('show')
+
+ if (this.hasContent() && this.enabled) {
+ this.$element.trigger(e)
+ if (e.isDefaultPrevented()) return
+ $tip = this.tip()
+ this.setContent()
+
+ if (this.options.animation) {
+ $tip.addClass('fade')
+ }
+
+ placement = typeof this.options.placement == 'function' ?
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
+ this.options.placement
+
+ $tip
+ .detach()
+ .css({ top: 0, left: 0, display: 'block' })
+
+ this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
+
+ pos = this.getPosition()
+
+ actualWidth = $tip[0].offsetWidth
+ actualHeight = $tip[0].offsetHeight
+
+ switch (placement) {
+ case 'bottom':
+ tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
+ break
+ case 'top':
+ tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
+ break
+ case 'left':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
+ break
+ case 'right':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
+ break
+ }
+
+ this.applyPlacement(tp, placement)
+ this.$element.trigger('shown')
+ }
+ }
+
+ , applyPlacement: function(offset, placement){
+ var $tip = this.tip()
+ , width = $tip[0].offsetWidth
+ , height = $tip[0].offsetHeight
+ , actualWidth
+ , actualHeight
+ , delta
+ , replace
+
+ $tip
+ .offset(offset)
+ .addClass(placement)
+ .addClass('in')
+
+ actualWidth = $tip[0].offsetWidth
+ actualHeight = $tip[0].offsetHeight
+
+ if (placement == 'top' && actualHeight != height) {
+ offset.top = offset.top + height - actualHeight
+ replace = true
+ }
+
+ if (placement == 'bottom' || placement == 'top') {
+ delta = 0
+
+ if (offset.left < 0){
+ delta = offset.left * -2
+ offset.left = 0
+ $tip.offset(offset)
+ actualWidth = $tip[0].offsetWidth
+ actualHeight = $tip[0].offsetHeight
+ }
+
+ this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
+ } else {
+ this.replaceArrow(actualHeight - height, actualHeight, 'top')
+ }
+
+ if (replace) $tip.offset(offset)
+ }
+
+ , replaceArrow: function(delta, dimension, position){
+ this
+ .arrow()
+ .css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
+ }
+
+ , setContent: function () {
+ var $tip = this.tip()
+ , title = this.getTitle()
+
+ $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
+ $tip.removeClass('fade in top bottom left right')
+ }
+
+ , hide: function () {
+ var that = this
+ , $tip = this.tip()
+ , e = $.Event('hide')
+
+ this.$element.trigger(e)
+ if (e.isDefaultPrevented()) return
+
+ $tip.removeClass('in')
+
+ function removeWithAnimation() {
+ var timeout = setTimeout(function () {
+ $tip.off($.support.transition.end).detach()
+ }, 500)
+
+ $tip.one($.support.transition.end, function () {
+ clearTimeout(timeout)
+ $tip.detach()
+ })
+ }
+
+ $.support.transition && this.$tip.hasClass('fade') ?
+ removeWithAnimation() :
+ $tip.detach()
+
+ this.$element.trigger('hidden')
+
+ return this
+ }
+
+ , fixTitle: function () {
+ var $e = this.$element
+ if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
+ $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
+ }
+ }
+
+ , hasContent: function () {
+ return this.getTitle()
+ }
+
+ , getPosition: function () {
+ var el = this.$element[0]
+ return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
+ width: el.offsetWidth
+ , height: el.offsetHeight
+ }, this.$element.offset())
+ }
+
+ , getTitle: function () {
+ var title
+ , $e = this.$element
+ , o = this.options
+
+ title = $e.attr('data-original-title')
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
+
+ return title
+ }
+
+ , tip: function () {
+ return this.$tip = this.$tip || $(this.options.template)
+ }
+
+ , arrow: function(){
+ return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
+ }
+
+ , validate: function () {
+ if (!this.$element[0].parentNode) {
+ this.hide()
+ this.$element = null
+ this.options = null
+ }
+ }
+
+ , enable: function () {
+ this.enabled = true
+ }
+
+ , disable: function () {
+ this.enabled = false
+ }
+
+ , toggleEnabled: function () {
+ this.enabled = !this.enabled
+ }
+
+ , toggle: function (e) {
+ var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this
+ self.tip().hasClass('in') ? self.hide() : self.show()
+ }
+
+ , destroy: function () {
+ this.hide().$element.off('.' + this.type).removeData(this.type)
+ }
+
+ }
+
+
+ /* TOOLTIP PLUGIN DEFINITION
+ * ========================= */
+
+ var old = $.fn.tooltip
+
+ $.fn.tooltip = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('tooltip')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.tooltip.Constructor = Tooltip
+
+ $.fn.tooltip.defaults = {
+ animation: true
+ , placement: 'top'
+ , selector: false
+ , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
+ , trigger: 'hover focus'
+ , title: ''
+ , delay: 0
+ , html: false
+ , container: false
+ }
+
+
+ /* TOOLTIP NO CONFLICT
+ * =================== */
+
+ $.fn.tooltip.noConflict = function () {
+ $.fn.tooltip = old
+ return this
+ }
+
+}(window.jQuery);
+/* ===========================================================
+ * bootstrap-popover.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#popovers
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* POPOVER PUBLIC CLASS DEFINITION
+ * =============================== */
+
+ var Popover = function (element, options) {
+ this.init('popover', element, options)
+ }
+
+
+ /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
+ ========================================== */
+
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
+
+ constructor: Popover
+
+ , setContent: function () {
+ var $tip = this.tip()
+ , title = this.getTitle()
+ , content = this.getContent()
+
+ $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+ $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
+
+ $tip.removeClass('fade top bottom left right in')
+ }
+
+ , hasContent: function () {
+ return this.getTitle() || this.getContent()
+ }
+
+ , getContent: function () {
+ var content
+ , $e = this.$element
+ , o = this.options
+
+ content = (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
+ || $e.attr('data-content')
+
+ return content
+ }
+
+ , tip: function () {
+ if (!this.$tip) {
+ this.$tip = $(this.options.template)
+ }
+ return this.$tip
+ }
+
+ , destroy: function () {
+ this.hide().$element.off('.' + this.type).removeData(this.type)
+ }
+
+ })
+
+
+ /* POPOVER PLUGIN DEFINITION
+ * ======================= */
+
+ var old = $.fn.popover
+
+ $.fn.popover = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('popover')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('popover', (data = new Popover(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.popover.Constructor = Popover
+
+ $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
+ placement: 'right'
+ , trigger: 'click'
+ , content: ''
+ , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+ })
+
+
+ /* POPOVER NO CONFLICT
+ * =================== */
+
+ $.fn.popover.noConflict = function () {
+ $.fn.popover = old
+ return this
+ }
+
+}(window.jQuery);
+/* =============================================================
+ * bootstrap-scrollspy.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#scrollspy
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* SCROLLSPY CLASS DEFINITION
+ * ========================== */
+
+ function ScrollSpy(element, options) {
+ var process = $.proxy(this.process, this)
+ , $element = $(element).is('body') ? $(window) : $(element)
+ , href
+ this.options = $.extend({}, $.fn.scrollspy.defaults, options)
+ this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)
+ this.selector = (this.options.target
+ || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+ || '') + ' .nav li > a'
+ this.$body = $('body')
+ this.refresh()
+ this.process()
+ }
+
+ ScrollSpy.prototype = {
+
+ constructor: ScrollSpy
+
+ , refresh: function () {
+ var self = this
+ , $targets
+
+ this.offsets = $([])
+ this.targets = $([])
+
+ $targets = this.$body
+ .find(this.selector)
+ .map(function () {
+ var $el = $(this)
+ , href = $el.data('target') || $el.attr('href')
+ , $href = /^#\w/.test(href) && $(href)
+ return ( $href
+ && $href.length
+ && [[ $href.position().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]] ) || null
+ })
+ .sort(function (a, b) { return a[0] - b[0] })
+ .each(function () {
+ self.offsets.push(this[0])
+ self.targets.push(this[1])
+ })
+ }
+
+ , process: function () {
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
+ , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
+ , maxScroll = scrollHeight - this.$scrollElement.height()
+ , offsets = this.offsets
+ , targets = this.targets
+ , activeTarget = this.activeTarget
+ , i
+
+ if (scrollTop >= maxScroll) {
+ return activeTarget != (i = targets.last()[0])
+ && this.activate ( i )
+ }
+
+ for (i = offsets.length; i--;) {
+ activeTarget != targets[i]
+ && scrollTop >= offsets[i]
+ && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
+ && this.activate( targets[i] )
+ }
+ }
+
+ , activate: function (target) {
+ var active
+ , selector
+
+ this.activeTarget = target
+
+ $(this.selector)
+ .parent('.active')
+ .removeClass('active')
+
+ selector = this.selector
+ + '[data-target="' + target + '"],'
+ + this.selector + '[href="' + target + '"]'
+
+ active = $(selector)
+ .parent('li')
+ .addClass('active')
+
+ if (active.parent('.dropdown-menu').length) {
+ active = active.closest('li.dropdown').addClass('active')
+ }
+
+ active.trigger('activate')
+ }
+
+ }
+
+
+ /* SCROLLSPY PLUGIN DEFINITION
+ * =========================== */
+
+ var old = $.fn.scrollspy
+
+ $.fn.scrollspy = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('scrollspy')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.scrollspy.Constructor = ScrollSpy
+
+ $.fn.scrollspy.defaults = {
+ offset: 10
+ }
+
+
+ /* SCROLLSPY NO CONFLICT
+ * ===================== */
+
+ $.fn.scrollspy.noConflict = function () {
+ $.fn.scrollspy = old
+ return this
+ }
+
+
+ /* SCROLLSPY DATA-API
+ * ================== */
+
+ $(window).on('load', function () {
+ $('[data-spy="scroll"]').each(function () {
+ var $spy = $(this)
+ $spy.scrollspy($spy.data())
+ })
+ })
+
+}(window.jQuery);/* ========================================================
+ * bootstrap-tab.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#tabs
+ * ========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* TAB CLASS DEFINITION
+ * ==================== */
+
+ var Tab = function (element) {
+ this.element = $(element)
+ }
+
+ Tab.prototype = {
+
+ constructor: Tab
+
+ , show: function () {
+ var $this = this.element
+ , $ul = $this.closest('ul:not(.dropdown-menu)')
+ , selector = $this.attr('data-target')
+ , previous
+ , $target
+ , e
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+ }
+
+ if ( $this.parent('li').hasClass('active') ) return
+
+ previous = $ul.find('.active:last a')[0]
+
+ e = $.Event('show', {
+ relatedTarget: previous
+ })
+
+ $this.trigger(e)
+
+ if (e.isDefaultPrevented()) return
+
+ $target = $(selector)
+
+ this.activate($this.parent('li'), $ul)
+ this.activate($target, $target.parent(), function () {
+ $this.trigger({
+ type: 'shown'
+ , relatedTarget: previous
+ })
+ })
+ }
+
+ , activate: function ( element, container, callback) {
+ var $active = container.find('> .active')
+ , transition = callback
+ && $.support.transition
+ && $active.hasClass('fade')
+
+ function next() {
+ $active
+ .removeClass('active')
+ .find('> .dropdown-menu > .active')
+ .removeClass('active')
+
+ element.addClass('active')
+
+ if (transition) {
+ element[0].offsetWidth // reflow for transition
+ element.addClass('in')
+ } else {
+ element.removeClass('fade')
+ }
+
+ if ( element.parent('.dropdown-menu') ) {
+ element.closest('li.dropdown').addClass('active')
+ }
+
+ callback && callback()
+ }
+
+ transition ?
+ $active.one($.support.transition.end, next) :
+ next()
+
+ $active.removeClass('in')
+ }
+ }
+
+
+ /* TAB PLUGIN DEFINITION
+ * ===================== */
+
+ var old = $.fn.tab
+
+ $.fn.tab = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('tab')
+ if (!data) $this.data('tab', (data = new Tab(this)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.tab.Constructor = Tab
+
+
+ /* TAB NO CONFLICT
+ * =============== */
+
+ $.fn.tab.noConflict = function () {
+ $.fn.tab = old
+ return this
+ }
+
+
+ /* TAB DATA-API
+ * ============ */
+
+ $(document).on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
+ e.preventDefault()
+ $(this).tab('show')
+ })
+
+}(window.jQuery);/* =============================================================
+ * bootstrap-typeahead.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#typeahead
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function($){
+
+ "use strict"; // jshint ;_;
+
+
+ /* TYPEAHEAD PUBLIC CLASS DEFINITION
+ * ================================= */
+
+ var Typeahead = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.typeahead.defaults, options)
+ this.matcher = this.options.matcher || this.matcher
+ this.sorter = this.options.sorter || this.sorter
+ this.highlighter = this.options.highlighter || this.highlighter
+ this.updater = this.options.updater || this.updater
+ this.source = this.options.source
+ this.$menu = $(this.options.menu)
+ this.shown = false
+ this.listen()
+ }
+
+ Typeahead.prototype = {
+
+ constructor: Typeahead
+
+ , select: function () {
+ var val = this.$menu.find('.active').attr('data-value')
+ this.$element
+ .val(this.updater(val))
+ .change()
+ return this.hide()
+ }
+
+ , updater: function (item) {
+ return item
+ }
+
+ , show: function () {
+ var pos = $.extend({}, this.$element.position(), {
+ height: this.$element[0].offsetHeight
+ })
+
+ this.$menu
+ .insertAfter(this.$element)
+ .css({
+ top: pos.top + pos.height
+ , left: pos.left
+ })
+ .show()
+
+ this.shown = true
+ return this
+ }
+
+ , hide: function () {
+ this.$menu.hide()
+ this.shown = false
+ return this
+ }
+
+ , lookup: function (event) {
+ var items
+
+ this.query = this.$element.val()
+
+ if (!this.query || this.query.length < this.options.minLength) {
+ return this.shown ? this.hide() : this
+ }
+
+ items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source
+
+ return items ? this.process(items) : this
+ }
+
+ , process: function (items) {
+ var that = this
+
+ items = $.grep(items, function (item) {
+ return that.matcher(item)
+ })
+
+ items = this.sorter(items)
+
+ if (!items.length) {
+ return this.shown ? this.hide() : this
+ }
+
+ return this.render(items.slice(0, this.options.items)).show()
+ }
+
+ , matcher: function (item) {
+ return ~item.toLowerCase().indexOf(this.query.toLowerCase())
+ }
+
+ , sorter: function (items) {
+ var beginswith = []
+ , caseSensitive = []
+ , caseInsensitive = []
+ , item
+
+ while (item = items.shift()) {
+ if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
+ else if (~item.indexOf(this.query)) caseSensitive.push(item)
+ else caseInsensitive.push(item)
+ }
+
+ return beginswith.concat(caseSensitive, caseInsensitive)
+ }
+
+ , highlighter: function (item) {
+ var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
+ return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
+ return '<strong>' + match + '</strong>'
+ })
+ }
+
+ , render: function (items) {
+ var that = this
+
+ items = $(items).map(function (i, item) {
+ i = $(that.options.item).attr('data-value', item)
+ i.find('a').html(that.highlighter(item))
+ return i[0]
+ })
+
+ items.first().addClass('active')
+ this.$menu.html(items)
+ return this
+ }
+
+ , next: function (event) {
+ var active = this.$menu.find('.active').removeClass('active')
+ , next = active.next()
+
+ if (!next.length) {
+ next = $(this.$menu.find('li')[0])
+ }
+
+ next.addClass('active')
+ }
+
+ , prev: function (event) {
+ var active = this.$menu.find('.active').removeClass('active')
+ , prev = active.prev()
+
+ if (!prev.length) {
+ prev = this.$menu.find('li').last()
+ }
+
+ prev.addClass('active')
+ }
+
+ , listen: function () {
+ this.$element
+ .on('focus', $.proxy(this.focus, this))
+ .on('blur', $.proxy(this.blur, this))
+ .on('keypress', $.proxy(this.keypress, this))
+ .on('keyup', $.proxy(this.keyup, this))
+
+ if (this.eventSupported('keydown')) {
+ this.$element.on('keydown', $.proxy(this.keydown, this))
+ }
+
+ this.$menu
+ .on('click', $.proxy(this.click, this))
+ .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
+ .on('mouseleave', 'li', $.proxy(this.mouseleave, this))
+ }
+
+ , eventSupported: function(eventName) {
+ var isSupported = eventName in this.$element
+ if (!isSupported) {
+ this.$element.setAttribute(eventName, 'return;')
+ isSupported = typeof this.$element[eventName] === 'function'
+ }
+ return isSupported
+ }
+
+ , move: function (e) {
+ if (!this.shown) return
+
+ switch(e.keyCode) {
+ case 9: // tab
+ case 13: // enter
+ case 27: // escape
+ e.preventDefault()
+ break
+
+ case 38: // up arrow
+ e.preventDefault()
+ this.prev()
+ break
+
+ case 40: // down arrow
+ e.preventDefault()
+ this.next()
+ break
+ }
+
+ e.stopPropagation()
+ }
+
+ , keydown: function (e) {
+ this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27])
+ this.move(e)
+ }
+
+ , keypress: function (e) {
+ if (this.suppressKeyPressRepeat) return
+ this.move(e)
+ }
+
+ , keyup: function (e) {
+ switch(e.keyCode) {
+ case 40: // down arrow
+ case 38: // up arrow
+ case 16: // shift
+ case 17: // ctrl
+ case 18: // alt
+ break
+
+ case 9: // tab
+ case 13: // enter
+ if (!this.shown) return
+ this.select()
+ break
+
+ case 27: // escape
+ if (!this.shown) return
+ this.hide()
+ break
+
+ default:
+ this.lookup()
+ }
+
+ e.stopPropagation()
+ e.preventDefault()
+ }
+
+ , focus: function (e) {
+ this.focused = true
+ }
+
+ , blur: function (e) {
+ this.focused = false
+ if (!this.mousedover && this.shown) this.hide()
+ }
+
+ , click: function (e) {
+ e.stopPropagation()
+ e.preventDefault()
+ this.select()
+ this.$element.focus()
+ }
+
+ , mouseenter: function (e) {
+ this.mousedover = true
+ this.$menu.find('.active').removeClass('active')
+ $(e.currentTarget).addClass('active')
+ }
+
+ , mouseleave: function (e) {
+ this.mousedover = false
+ if (!this.focused && this.shown) this.hide()
+ }
+
+ }
+
+
+ /* TYPEAHEAD PLUGIN DEFINITION
+ * =========================== */
+
+ var old = $.fn.typeahead
+
+ $.fn.typeahead = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('typeahead')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.typeahead.defaults = {
+ source: []
+ , items: 8
+ , menu: '<ul class="typeahead dropdown-menu"></ul>'
+ , item: '<li><a href="#"></a></li>'
+ , minLength: 1
+ }
+
+ $.fn.typeahead.Constructor = Typeahead
+
+
+ /* TYPEAHEAD NO CONFLICT
+ * =================== */
+
+ $.fn.typeahead.noConflict = function () {
+ $.fn.typeahead = old
+ return this
+ }
+
+
+ /* TYPEAHEAD DATA-API
+ * ================== */
+
+ $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
+ var $this = $(this)
+ if ($this.data('typeahead')) return
+ $this.typeahead($this.data())
+ })
+
+}(window.jQuery);
+/* ==========================================================
+ * bootstrap-affix.js v2.3.1
+ * http://twitter.github.com/bootstrap/javascript.html#affix
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+ "use strict"; // jshint ;_;
+
+
+ /* AFFIX CLASS DEFINITION
+ * ====================== */
+
+ var Affix = function (element, options) {
+ this.options = $.extend({}, $.fn.affix.defaults, options)
+ this.$window = $(window)
+ .on('scroll.affix.data-api', $.proxy(this.checkPosition, this))
+ .on('click.affix.data-api', $.proxy(function () { setTimeout($.proxy(this.checkPosition, this), 1) }, this))
+ this.$element = $(element)
+ this.checkPosition()
+ }
+
+ Affix.prototype.checkPosition = function () {
+ if (!this.$element.is(':visible')) return
+
+ var scrollHeight = $(document).height()
+ , scrollTop = this.$window.scrollTop()
+ , position = this.$element.offset()
+ , offset = this.options.offset
+ , offsetBottom = offset.bottom
+ , offsetTop = offset.top
+ , reset = 'affix affix-top affix-bottom'
+ , affix
+
+ if (typeof offset != 'object') offsetBottom = offsetTop = offset
+ if (typeof offsetTop == 'function') offsetTop = offset.top()
+ if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
+
+ affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ?
+ false : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ?
+ 'bottom' : offsetTop != null && scrollTop <= offsetTop ?
+ 'top' : false
+
+ if (this.affixed === affix) return
+
+ this.affixed = affix
+ this.unpin = affix == 'bottom' ? position.top - scrollTop : null
+
+ this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : ''))
+ }
+
+
+ /* AFFIX PLUGIN DEFINITION
+ * ======================= */
+
+ var old = $.fn.affix
+
+ $.fn.affix = function (option) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('affix')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('affix', (data = new Affix(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.affix.Constructor = Affix
+
+ $.fn.affix.defaults = {
+ offset: 0
+ }
+
+
+ /* AFFIX NO CONFLICT
+ * ================= */
+
+ $.fn.affix.noConflict = function () {
+ $.fn.affix = old
+ return this
+ }
+
+
+ /* AFFIX DATA-API
+ * ============== */
+
+ $(window).on('load', function () {
+ $('[data-spy="affix"]').each(function () {
+ var $spy = $(this)
+ , data = $spy.data()
+
+ data.offset = data.offset || {}
+
+ data.offsetBottom && (data.offset.bottom = data.offsetBottom)
+ data.offsetTop && (data.offset.top = data.offsetTop)
+
+ $spy.affix(data)
+ })
+ })
+
+
+}(window.jQuery);
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/js/bootstrap.min.js b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/js/bootstrap.min.js
new file mode 100644
index 0000000..95c5ac5
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/resources/js/bootstrap.min.js
@@ -0,0 +1,6 @@
+/*!
+* Bootstrap.js by @fat & @mdo
+* Copyright 2012 Twitter, Inc.
+* http://www.apache.org/licenses/LICENSE-2.0.txt
+*/
+!function(e){"use strict";e(function(){e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()};var r=e.fn.alert;e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e.fn.alert.noConflict=function(){return e.fn.alert=r,this},e(document).on("click.alert.data-api",t,n.prototype.close)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")};var n=e.fn.button;e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.defaults={loadingText:"loading..."},e.fn.button.Constructor=t,e.fn.button.noConflict=function(){return e.fn.button=n,this},e(document).on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.$indicators=this.$element.find(".carousel-indicators"),this.options=n,this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},getActiveIndex:function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},to:function(t){var n=this.getActiveIndex(),r=this;if(t>this.$items.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){r.to(t)}):n==t?this.pause().cycle():this.slide(t>n?"next":"prev",e(this.$items[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle(!0)),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f;this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u](),f=e.Event("slide",{relatedTarget:i[0],direction:o});if(i.hasClass("active"))return;this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var t=e(a.$indicators.children()[a.getActiveIndex()]);t&&t.addClass("active")}));if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}};var n=e.fn.carousel;e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.pause().cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Constructor=t,e.fn.carousel.noConflict=function(){return e.fn.carousel=n,this},e(document).on("click.carousel.data-api","[data-slide], [data-slide-to]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=e.extend({},i.data(),n.data()),o;i.carousel(s),(o=n.attr("data-slide-to"))&&i.data("carousel").pause().to(o).cycle(),t.preventDefault()})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hasClass("width");return e?"width":"height"},show:function(){var t,n,r,i;if(this.transitioning||this.$element.hasClass("in"))return;t=this.dimension(),n=e.camelCase(["scroll",t].join("-")),r=this.$parent&&this.$parent.find("> .accordion-group > .in");if(r&&r.length){i=r.data("collapse");if(i&&i.transitioning)return;r.collapse("hide"),i||r.data("collapse",null)}this.$element[t](0),this.transition("addClass",e.Event("show"),"shown"),e.support.transition&&this.$element[t](this.$element[0][n])},hide:function(){var t;if(this.transitioning||!this.$element.hasClass("in"))return;t=this.dimension(),this.reset(this.$element[t]()),this.transition("removeClass",e.Event("hide"),"hidden"),this.$element[t](0)},reset:function(e){var t=this.dimension();return this.$element.removeClass("collapse")[t](e||"auto")[0].offsetWidth,this.$element[e!==null?"addClass":"removeClass"]("collapse"),this},transition:function(t,n,r){var i=this,s=function(){n.type=="show"&&i.reset(),i.transitioning=0,i.$element.trigger(r)};this.$element.trigger(n);if(n.isDefaultPrevented())return;this.transitioning=1,this.$element[t]("in"),e.support.transition&&this.$element.hasClass("collapse")?this.$element.one(e.support.transition.end,s):s()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}};var n=e.fn.collapse;e.fn.collapse=function(n){return this.each(function(){var r=e(this),i=r.data("collapse"),s=e.extend({},e.fn.collapse.defaults,r.data(),typeof n=="object"&&n);i||r.data("collapse",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.collapse.defaults={toggle:!0},e.fn.collapse.Constructor=t,e.fn.collapse.noConflict=function(){return e.fn.collapse=n,this},e(document).on("click.collapse.data-api","[data-toggle=collapse]",function(t){var n=e(this),r,i=n.attr("data-target")||t.preventDefault()||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,""),s=e(i).data("collapse")?"toggle":n.data();n[e(i).hasClass("in")?"addClass":"removeClass"]("collapsed"),e(i).collapse(s)})}(window.jQuery),!function(e){"use strict";function r(){e(t).each(function(){i(e(this)).removeClass("open")})}function i(t){var n=t.attr("data-target"),r;n||(n=t.attr("href"),n=n&&/#/.test(n)&&n.replace(/.*(?=#[^\s]*$)/,"")),r=n&&e(n);if(!r||!r.length)r=t.parent();return r}var t="[data-toggle=dropdown]",n=function(t){var n=e(t).on("click.dropdown.data-api",this.toggle);e("html").on("click.dropdown.data-api",function(){n.parent().removeClass("open")})};n.prototype={constructor:n,toggle:function(t){var n=e(this),s,o;if(n.is(".disabled, :disabled"))return;return s=i(n),o=s.hasClass("open"),r(),o||s.toggleClass("open"),n.focus(),!1},keydown:function(n){var r,s,o,u,a,f;if(!/(38|40|27)/.test(n.keyCode))return;r=e(this),n.preventDefault(),n.stopPropagation();if(r.is(".disabled, :disabled"))return;u=i(r),a=u.hasClass("open");if(!a||a&&n.keyCode==27)return n.which==27&&u.find(t).focus(),r.click();s=e("[role=menu] li:not(.divider):visible a",u);if(!s.length)return;f=s.index(s.filter(":focus")),n.keyCode==38&&f>0&&f--,n.keyCode==40&&f<s.length-1&&f++,~f||(f=0),s.eq(f).focus()}};var s=e.fn.dropdown;e.fn.dropdown=function(t){return this.each(function(){var r=e(this),i=r.data("dropdown");i||r.data("dropdown",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.dropdown.Constructor=n,e.fn.dropdown.noConflict=function(){return e.fn.dropdown=s,this},e(document).on("click.dropdown.data-api",r).on("click.dropdown.data-api",".dropdown form",function(e){e.stopPropagation()}).on("click.dropdown-menu",function(e){e.stopPropagation()}).on("click.dropdown.data-api",t,n.prototype.toggle).on("keydown.dropdown.data-api",t+", [role=menu]",n.prototype.keydown)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=n,this.$element=e(t).delegate('[data-dismiss="modal"]',"click.dismiss.modal",e.proxy(this.hide,this)),this.options.remote&&this.$element.find(".modal-body").load(this.options.remote)};t.prototype={constructor:t,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var t=this,n=e.Event("show");this.$element.trigger(n);if(this.isShown||n.isDefaultPrevented())return;this.isShown=!0,this.escape(),this.backdrop(function(){var n=e.support.transition&&t.$element.hasClass("fade");t.$element.parent().length||t.$element.appendTo(document.body),t.$element.show(),n&&t.$element[0].offsetWidth,t.$element.addClass("in").attr("aria-hidden",!1),t.enforceFocus(),n?t.$element.one(e.support.transition.end,function(){t.$element.focus().trigger("shown")}):t.$element.focus().trigger("shown")})},hide:function(t){t&&t.preventDefault();var n=this;t=e.Event("hide"),this.$element.trigger(t);if(!this.isShown||t.isDefaultPrevented())return;this.isShown=!1,this.escape(),e(document).off("focusin.modal"),this.$element.removeClass("in").attr("aria-hidden",!0),e.support.transition&&this.$element.hasClass("fade")?this.hideWithTransition():this.hideModal()},enforceFocus:function(){var t=this;e(document).on("focusin.modal",function(e){t.$element[0]!==e.target&&!t.$element.has(e.target).length&&t.$element.focus()})},escape:function(){var e=this;this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.modal",function(t){t.which==27&&e.hide()}):this.isShown||this.$element.off("keyup.dismiss.modal")},hideWithTransition:function(){var t=this,n=setTimeout(function(){t.$element.off(e.support.transition.end),t.hideModal()},500);this.$element.one(e.support.transition.end,function(){clearTimeout(n),t.hideModal()})},hideModal:function(){var e=this;this.$element.hide(),this.backdrop(function(){e.removeBackdrop(),e.$element.trigger("hidden")})},removeBackdrop:function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},backdrop:function(t){var n=this,r=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var i=e.support.transition&&r;this.$backdrop=e('<div class="modal-backdrop '+r+'" />').appendTo(document.body),this.$backdrop.click(this.options.backdrop=="static"?e.proxy(this.$element[0].focus,this.$element[0]):e.proxy(this.hide,this)),i&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in");if(!t)return;i?this.$backdrop.one(e.support.transition.end,t):t()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),e.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(e.support.transition.end,t):t()):t&&t()}};var n=e.fn.modal;e.fn.modal=function(n){return this.each(function(){var r=e(this),i=r.data("modal"),s=e.extend({},e.fn.modal.defaults,r.data(),typeof n=="object"&&n);i||r.data("modal",i=new t(this,s)),typeof n=="string"?i[n]():s.show&&i.show()})},e.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},e.fn.modal.Constructor=t,e.fn.modal.noConflict=function(){return e.fn.modal=n,this},e(document).on("click.modal.data-api",'[data-toggle="modal"]',function(t){var n=e(this),r=n.attr("href"),i=e(n.attr("data-target")||r&&r.replace(/.*(?=#[^\s]+$)/,"")),s=i.data("modal")?"toggle":e.extend({remote:!/#/.test(r)&&r},i.data(),n.data());t.preventDefault(),i.modal(s).one("hide",function(){n.focus()})})}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("tooltip",e,t)};t.prototype={constructor:t,init:function(t,n,r){var i,s,o,u,a;this.type=t,this.$element=e(n),this.options=this.getOptions(r),this.enabled=!0,o=this.options.trigger.split(" ");for(a=o.length;a--;)u=o[a],u=="click"?this.$element.on("click."+this.type,this.options.selector,e.proxy(this.toggle,this)):u!="manual"&&(i=u=="hover"?"mouseenter":"focus",s=u=="hover"?"mouseleave":"blur",this.$element.on(i+"."+this.type,this.options.selector,e.proxy(this.enter,this)),this.$element.on(s+"."+this.type,this.options.selector,e.proxy(this.leave,this)));this.options.selector?this._options=e.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(t){return t=e.extend({},e.fn[this.type].defaults,this.$element.data(),t),t.delay&&typeof t.delay=="number"&&(t.delay={show:t.delay,hide:t.delay}),t},enter:function(t){var n=e.fn[this.type].defaults,r={},i;this._options&&e.each(this._options,function(e,t){n[e]!=t&&(r[e]=t)},this),i=e(t.currentTarget)[this.type](r).data(this.type);if(!i.options.delay||!i.options.delay.show)return i.show();clearTimeout(this.timeout),i.hoverState="in",this.timeout=setTimeout(function(){i.hoverState=="in"&&i.show()},i.options.delay.show)},leave:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!n.options.delay||!n.options.delay.hide)return n.hide();n.hoverState="out",this.timeout=setTimeout(function(){n.hoverState=="out"&&n.hide()},n.options.delay.hide)},show:function(){var t,n,r,i,s,o,u=e.Event("show");if(this.hasContent()&&this.enabled){this.$element.trigger(u);if(u.isDefaultPrevented())return;t=this.tip(),this.setContent(),this.options.animation&&t.addClass("fade"),s=typeof this.options.placement=="function"?this.options.placement.call(this,t[0],this.$element[0]):this.options.placement,t.detach().css({top:0,left:0,display:"block"}),this.options.container?t.appendTo(this.options.container):t.insertAfter(this.$element),n=this.getPosition(),r=t[0].offsetWidth,i=t[0].offsetHeight;switch(s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}this.applyPlacement(o,s),this.$element.trigger("shown")}},applyPlacement:function(e,t){var n=this.tip(),r=n[0].offsetWidth,i=n[0].offsetHeight,s,o,u,a;n.offset(e).addClass(t).addClass("in"),s=n[0].offsetWidth,o=n[0].offsetHeight,t=="top"&&o!=i&&(e.top=e.top+i-o,a=!0),t=="bottom"||t=="top"?(u=0,e.left<0&&(u=e.left*-2,e.left=0,n.offset(e),s=n[0].offsetWidth,o=n[0].offsetHeight),this.replaceArrow(u-r+s,s,"left")):this.replaceArrow(o-i,o,"top"),a&&n.offset(e)},replaceArrow:function(e,t,n){this.arrow().css(n,e?50*(1-e/t)+"%":"")},setContent:function(){var e=this.tip(),t=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](t),e.removeClass("fade in top bottom left right")},hide:function(){function i(){var t=setTimeout(function(){n.off(e.support.transition.end).detach()},500);n.one(e.support.transition.end,function(){clearTimeout(t),n.detach()})}var t=this,n=this.tip(),r=e.Event("hide");this.$element.trigger(r);if(r.isDefaultPrevented())return;return n.removeClass("in"),e.support.transition&&this.$tip.hasClass("fade")?i():n.detach(),this.$element.trigger("hidden"),this},fixTitle:function(){var e=this.$element;(e.attr("title")||typeof e.attr("data-original-title")!="string")&&e.attr("data-original-title",e.attr("title")||"").attr("title","")},hasContent:function(){return this.getTitle()},getPosition:function(){var t=this.$element[0];return e.extend({},typeof t.getBoundingClientRect=="function"?t.getBoundingClientRect():{width:t.offsetWidth,height:t.offsetHeight},this.$element.offset())},getTitle:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-original-title")||(typeof n.title=="function"?n.title.call(t[0]):n.title),e},tip:function(){return this.$tip=this.$tip||e(this.options.template)},arrow:function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(t){var n=t?e(t.currentTarget)[this.type](this._options).data(this.type):this;n.tip().hasClass("in")?n.hide():n.show()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}};var n=e.fn.tooltip;e.fn.tooltip=function(n){return this.each(function(){var r=e(this),i=r.data("tooltip"),s=typeof n=="object"&&n;i||r.data("tooltip",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.tooltip.Constructor=t,e.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},e.fn.tooltip.noConflict=function(){return e.fn.tooltip=n,this}}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("popover",e,t)};t.prototype=e.extend({},e.fn.tooltip.Constructor.prototype,{constructor:t,setContent:function(){var e=this.tip(),t=this.getTitle(),n=this.getContent();e.find(".popover-title")[this.options.html?"html":"text"](t),e.find(".popover-content")[this.options.html?"html":"text"](n),e.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var e,t=this.$element,n=this.options;return e=(typeof n.content=="function"?n.content.call(t[0]):n.content)||t.attr("data-content"),e},tip:function(){return this.$tip||(this.$tip=e(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}});var n=e.fn.popover;e.fn.popover=function(n){return this.each(function(){var r=e(this),i=r.data("popover"),s=typeof n=="object"&&n;i||r.data("popover",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.popover.Constructor=t,e.fn.popover.defaults=e.extend({},e.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),e.fn.popover.noConflict=function(){return e.fn.popover=n,this}}(window.jQuery),!function(e){"use strict";function t(t,n){var r=e.proxy(this.process,this),i=e(t).is("body")?e(window):e(t),s;this.options=e.extend({},e.fn.scrollspy.defaults,n),this.$scrollElement=i.on("scroll.scroll-spy.data-api",r),this.selector=(this.options.target||(s=e(t).attr("href"))&&s.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=e("body"),this.refresh(),this.process()}t.prototype={constructor:t,refresh:function(){var t=this,n;this.offsets=e([]),this.targets=e([]),n=this.$body.find(this.selector).map(function(){var n=e(this),r=n.data("target")||n.attr("href"),i=/^#\w/.test(r)&&e(r);return i&&i.length&&[[i.position().top+(!e.isWindow(t.$scrollElement.get(0))&&t.$scrollElement.scrollTop()),r]]||null}).sort(function(e,t){return e[0]-t[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},process:function(){var e=this.$scrollElement.scrollTop()+this.options.offset,t=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,n=t-this.$scrollElement.height(),r=this.offsets,i=this.targets,s=this.activeTarget,o;if(e>=n)return s!=(o=i.last()[0])&&this.activate(o);for(o=r.length;o--;)s!=i[o]&&e>=r[o]&&(!r[o+1]||e<=r[o+1])&&this.activate(i[o])},activate:function(t){var n,r;this.activeTarget=t,e(this.selector).parent(".active").removeClass("active"),r=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',n=e(r).parent("li").addClass("active"),n.parent(".dropdown-menu").length&&(n=n.closest("li.dropdown").addClass("active")),n.trigger("activate")}};var n=e.fn.scrollspy;e.fn.scrollspy=function(n){return this.each(function(){var r=e(this),i=r.data("scrollspy"),s=typeof n=="object"&&n;i||r.data("scrollspy",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.scrollspy.Constructor=t,e.fn.scrollspy.defaults={offset:10},e.fn.scrollspy.noConflict=function(){return e.fn.scrollspy=n,this},e(window).on("load",function(){e('[data-spy="scroll"]').each(function(){var t=e(this);t.scrollspy(t.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t){this.element=e(t)};t.prototype={constructor:t,show:function(){var t=this.element,n=t.closest("ul:not(.dropdown-menu)"),r=t.attr("data-target"),i,s,o;r||(r=t.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,""));if(t.parent("li").hasClass("active"))return;i=n.find(".active:last a")[0],o=e.Event("show",{relatedTarget:i}),t.trigger(o);if(o.isDefaultPrevented())return;s=e(r),this.activate(t.parent("li"),n),this.activate(s,s.parent(),function(){t.trigger({type:"shown",relatedTarget:i})})},activate:function(t,n,r){function o(){i.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),t.addClass("active"),s?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu")&&t.closest("li.dropdown").addClass("active"),r&&r()}var i=n.find("> .active"),s=r&&e.support.transition&&i.hasClass("fade");s?i.one(e.support.transition.end,o):o(),i.removeClass("in")}};var n=e.fn.tab;e.fn.tab=function(n){return this.each(function(){var r=e(this),i=r.data("tab");i||r.data("tab",i=new t(this)),typeof n=="string"&&i[n]()})},e.fn.tab.Constructor=t,e.fn.tab.noConflict=function(){return e.fn.tab=n,this},e(document).on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(t){t.preventDefault(),e(this).tab("show")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.$menu=e(this.options.menu),this.shown=!1,this.listen()};t.prototype={constructor:t,select:function(){var e=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(e)).change(),this.hide()},updater:function(e){return e},show:function(){var t=e.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:t.top+t.height,left:t.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(n=e.isFunction(this.source)?this.source(this.query,e.proxy(this.process,this)):this.source,n?this.process(n):this)},process:function(t){var n=this;return t=e.grep(t,function(e){return n.matcher(e)}),t=this.sorter(t),t.length?this.render(t.slice(0,this.options.items)).show():this.shown?this.hide():this},matcher:function(e){return~e.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(e){var t=[],n=[],r=[],i;while(i=e.shift())i.toLowerCase().indexOf(this.query.toLowerCase())?~i.indexOf(this.query)?n.push(i):r.push(i):t.push(i);return t.concat(n,r)},highlighter:function(e){var t=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return e.replace(new RegExp("("+t+")","ig"),function(e,t){return"<strong>"+t+"</strong>"})},render:function(t){var n=this;return t=e(t).map(function(t,r){return t=e(n.options.item).attr("data-value",r),t.find("a").html(n.highlighter(r)),t[0]}),t.first().addClass("active"),this.$menu.html(t),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.next();r.length||(r=e(this.$menu.find("li")[0])),r.addClass("active")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prev();n.length||(n=this.$menu.find("li").last()),n.addClass("active")},listen:function(){this.$element.on("focus",e.proxy(this.focus,this)).on("blur",e.proxy(this.blur,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this)).on("mouseleave","li",e.proxy(this.mouseleave,this))},eventSupported:function(e){var t=e in this.$element;return t||(this.$element.setAttribute(e,"return;"),t=typeof this.$element[e]=="function"),t},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},focus:function(e){this.focused=!0},blur:function(e){this.focused=!1,!this.mousedover&&this.shown&&this.hide()},click:function(e){e.stopPropagation(),e.preventDefault(),this.select(),this.$element.focus()},mouseenter:function(t){this.mousedover=!0,this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")},mouseleave:function(e){this.mousedover=!1,!this.focused&&this.shown&&this.hide()}};var n=e.fn.typeahead;e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1},e.fn.typeahead.Constructor=t,e.fn.typeahead.noConflict=function(){return e.fn.typeahead=n,this},e(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;n.typeahead(n.data())})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=e.extend({},e.fn.affix.defaults,n),this.$window=e(window).on("scroll.affix.data-api",e.proxy(this.checkPosition,this)).on("click.affix.data-api",e.proxy(function(){setTimeout(e.proxy(this.checkPosition,this),1)},this)),this.$element=e(t),this.checkPosition()};t.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var t=e(document).height(),n=this.$window.scrollTop(),r=this.$element.offset(),i=this.options.offset,s=i.bottom,o=i.top,u="affix affix-top affix-bottom",a;typeof i!="object"&&(s=o=i),typeof o=="function"&&(o=i.top()),typeof s=="function"&&(s=i.bottom()),a=this.unpin!=null&&n+this.unpin<=r.top?!1:s!=null&&r.top+this.$element.height()>=t-s?"bottom":o!=null&&n<=o?"top":!1;if(this.affixed===a)return;this.affixed=a,this.unpin=a=="bottom"?r.top-n:null,this.$element.removeClass(u).addClass("affix"+(a?"-"+a:""))};var n=e.fn.affix;e.fn.affix=function(n){return this.each(function(){var r=e(this),i=r.data("affix"),s=typeof n=="object"&&n;i||r.data("affix",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.affix.Constructor=t,e.fn.affix.defaults={offset:0},e.fn.affix.noConflict=function(){return e.fn.affix=n,this},e(window).on("load",function(){e('[data-spy="affix"]').each(function(){var t=e(this),n=t.data();n.offset=n.offset||{},n.offsetBottom&&(n.offset.bottom=n.offsetBottom),n.offsetTop&&(n.offset.top=n.offsetTop),t.affix(n)})})}(window.jQuery);
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml
new file mode 100644
index 0000000..7e780e1
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans:beans xmlns="http://www.springframework.org/schema/mvc"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
+
+ <!-- DispatcherServlet Context: defines this servlet's request-processing
+ infrastructure -->
+
+ <!-- Enables the Spring MVC @Controller programming model -->
+ <annotation-driven />
+
+ <!-- Handles HTTP GET requests for /resources/** by efficiently serving
+ up static resources in the ${webappRoot}/resources directory -->
+ <resources mapping="/resources/**" location="/resources/" />
+
+ <!-- Resolves views selected for rendering by @Controllers to .jsp resources
+ in the /WEB-INF/views directory -->
+ <beans:bean id="templateResolver"
+ class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
+ <beans:property name="prefix" value="/WEB-INF/views/" />
+ <beans:property name="suffix" value=".html" />
+ <beans:property name="templateMode" value="HTML5" />
+ </beans:bean>
+
+ <beans:bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
+ <beans:property name="templateResolver" ref="templateResolver" />
+ <beans:property name="additionalDialects">
+ <beans:set>
+ <beans:bean class="nz.net.ultraq.thymeleaf.LayoutDialect" />
+ </beans:set>
+ </beans:property>
+ </beans:bean>
+
+ <beans:bean class="org.thymeleaf.spring3.view.ThymeleafViewResolver">
+ <beans:property name="templateEngine" ref="templateEngine" />
+ <beans:property name="order" value="1" />
+ </beans:bean>
+
+ <beans:bean
+ class="org.springframework.web.servlet.view.InternalResourceViewResolver">
+ <beans:property name="prefix" value="/WEB-INF/views/" />
+ <beans:property name="order" value="2" />
+ <beans:property name="suffix" value=".html" />
+ </beans:bean>
+
+ <beans:bean name="main" class="org.thymeleaf.spring3.view.ThymeleafView">
+ <beans:property name="staticVariables">
+ <beans:map>
+ <beans:entry key="footer" value="Some company: <b>ACME</b>" />
+ </beans:map>
+ </beans:property>
+ </beans:bean>
+
+ <context:component-scan base-package="eu.cloudscale.showcase.servlets" />
+
+</beans:beans>
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/spring/root-context.xml b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/spring/root-context.xml
new file mode 100644
index 0000000..9cbb4aa
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/spring/root-context.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+ <!-- Root Context: defines shared resources visible to all other web components -->
+ <import resource="classpath:app-context.xml" />
+</beans>
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/best-sellers.html b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/best-sellers.html
new file mode 100644
index 0000000..09896ec
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/best-sellers.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+ layout:decorator="/templates/layout">
+ <head>
+ <title>Best sellers</title>
+ </head>
+<body>
+<div layout:fragment="content">
+
+ <div class="jumbotron">
+ <h1>TPC Web Commerce Benchmark (TPC-W)</h1>
+ </div>
+ <div class="promotional">
+ <div class="pull-left" th:each="item : ${promotional}">
+ <a th:href="@{'/product-detail?I_ID=' + ${item.IId} + '' + ${productUrl}}">
+ <img th:src="@{${imgResourceUrl}} + '/' + ${item.IThumbnail}" src="" width="100" height="100" />
+ </a>
+ </div>
+ <div class="clearfix"></div>
+ </div>
+
+ <hr />
+
+ <table>
+ <thead>
+ <tr>
+ <th style="width: 50px; font-weight: bold;">
+ #
+ </th>
+ <th>
+ Author
+ </th>
+ <th>
+ Title
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr th:each="item, count : ${products}">
+ <td style="width: 50px; font-weight: bold;" th:text="${count.count}"></td>
+<!-- <td th:text="${item}"></td> -->
+ <td th:text="${item[2] + ' ' + item[3]}">
+ </td>
+ <td>
+ <a th:href="@{'/product-detail?I_ID=' + ${item[0]} + '' + ${productUrl}}" th:text="${item[1]}"></a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <div class="footer">
+ </div>
+</div>
+</body>
+</html>
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/buy.html b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/buy.html
new file mode 100644
index 0000000..e98eca9
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/buy.html
@@ -0,0 +1,188 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+ layout:decorator="/templates/layout">
+ <head>
+ <title>Buy</title>
+ </head>
+<body>
+<div layout:fragment="content">
+ <div class="container-narrow">
+ <div th:if="${!errors.isEmpty()}" class="alert alert-error">
+ <div th:each="error : ${errors}" th:text="${error}"></div>
+ </div>
+ <div th:unless="${!errors.isEmpty()}">
+ <form th:action="@{/buy-confirm(C_ID=${customer.CId})}" method="get">
+ <div class="billing-info">
+ <h2>Billing information:</h2>
+ <table>
+ <tr>
+ <td>Firstname:</td>
+ <td th:text="${customer.CFname}"></td>
+ </tr>
+ <tr>
+ <td>Lastname:</td>
+ <td th:text="${customer.CLname}"></td>
+ </tr>
+ </table>
+ <div class="pull-left myLabel">Address street1:</div>
+ <div class="pull-left content"
+ th:text="${customer.address.addrStreet1}"></div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">Address street2:</div>
+ <div class="pull-left content"
+ th:text="${customer.address.addrStreet2}"></div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">City:</div>
+ <div class="pull-left content"
+ th:text="${customer.address.addrCity}"></div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">State:</div>
+ <div class="pull-left content"
+ th:text="${customer.address.addrState}"></div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">Zip:</div>
+ <div class="pull-left content"
+ th:text="${customer.address.addrZip}"></div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">Country:</div>
+ <div class="pull-left content"
+ th:text="${customer.address.country.coName}"></div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">Email</div>
+ <div class="pull-left content" th:text="${customer.CEmail}">
+ </div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">Phone:</div>
+ <div class="pull-left content" th:text="${customer.CPhone}">
+ </div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">Address street1:</div>
+ <div class="pull-left content"
+ th:text="${customer.address.addrStreet1}"></div>
+ <div class="clearfix"></div>
+ </div>
+ <hr />
+ <div class="shipping-info">
+ <h2>Shipping information:</h2>
+ <div class="pull-left myLabel">Address street1:</div>
+ <div class="pull-left content">
+ <input type="text" name="street1" />
+ </div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">Address street 2:</div>
+ <div class="pull-left content">
+ <input type="text" name="street2" />
+ </div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">City:</div>
+ <div class="pull-left content">
+ <input type="text" name="city" />
+ </div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">State:</div>
+ <div class="pull-left content">
+ <input type="text" name="state" />
+ </div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">Zip:</div>
+ <div class="pull-left content">
+ <input type="text" name="zip" />
+ </div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">Country:</div>
+ <div class="pull-left content">
+ <input type="text" name="country" />
+ </div>
+ <div class="clearfix"></div>
+ </div>
+ <div class="clearfix"></div>
+ <hr />
+ <h2>Order information:</h2>
+ <div>
+ <table class="table">
+ <thead>
+ <tr>
+ <th>OTY</th>
+ <th>Product</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr th:each="line, i : ${cart.shoppingCartLines}">
+ <td th:text="${line.sclQty}"></td>
+ <td>Title: <i th:text="${line.item.ITitle}"></i> - Backing:
+ <span th:text="${line.item.IBacking}"></span><br /> SRP. $<span
+ th:text="${line.item.ISrp}"></span> <span style="color: red;"><strong>Your
+ Price: <span th:text="${line.item.ICost}"></span>
+ </strong></span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <div>
+ Subtotal width discount (0.0%): $<span th:text="${subTotal}"></span><br />
+ Tax:<br /> Shipping and Handling: <br /> Total: $<span
+ th:text="${subTotal}"></span><br />
+ </div>
+ <hr />
+ <div class="payment">
+ <div class="pull-left myLabel">CreditCartType</div>
+ <div class="pull-left content">
+ <label class="radio pull-left"> <input type="radio"
+ name="CC_TYPE" value="Visa" checked="checked" />Visa
+ </label> <label class="radio pull-left"> <input type="radio"
+ name="CC_TYPE" value="MasterCard" />MasterCard
+ </label> <label class="radio pull-left"> <input type="radio"
+ name="CC_TYPE" value="Discover" />Discover
+ </label> <label class="radio pull-left"> <input type="radio"
+ name="CC_TYPE" value="Amex" />American Express
+ </label> <label class="radio pull-left"> <input type="radio"
+ name="CC_TYPE" value="Diners" />Diners
+ </label>
+ </div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">Name on Credit Card</div>
+ <div class="pull-left content">
+ <input name="CC_NAME" />
+ </div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">Credit Card Number</div>
+ <div class="pull-left content">
+ <input name="CC_NUMBER" />
+ </div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">Credit Card Expiration Date
+ (mm/dd/yyyy)</div>
+ <div class="pull-left content">
+ <input name="CC_EXPIRY" />
+ </div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">Shipping method</div>
+ <div class="pull-left content">
+ <label class="radio pull-left"> <input type="radio"
+ name="SHIPPING" value="AIR" checked="checked" />AIR
+ </label> <label class="radio pull-left"> <input type="radio"
+ name="SHIPPING" value="UPS" />UPS
+ </label> <label class="radio pull-left"> <input type="radio"
+ name="SHIPPING" value="FEDEX" />FEDEX
+ </label> <label class="radio pull-left"> <input type="radio"
+ name="SHIPPING" value="SHIP" />SHIP
+ </label> <label class="radio pull-left"> <input type="radio"
+ name="SHIPPING" value="COURIER" />COURIER
+ </label> <label class="radio pull-left"> <input type="radio"
+ name="SHIPPING" value="MAIL" />MAIL
+ </label>
+ </div>
+ <div class="clearfix"></div>
+ </div>
+ <input th:if="${cart}" th:value="${cart.scId}" type="hidden"
+ name="SHOPPING_ID" /> <input th:if="${customer}"
+ th:value="${customer.CId}" type="hidden" name="C_ID" /> <input
+ class="btn btn-primary" type="submit" value="Submit" />
+ </form>
+ </div>
+ </div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/buy-confirm.html b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/buy-confirm.html
new file mode 100644
index 0000000..680b1d3
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/buy-confirm.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+ layout:decorator="/templates/layout">
+ <head>
+ <title>Buy confirm</title>
+ </head>
+<body>
+<div layout:fragment="content">
+ <div th:if="${!errors.isEmpty()}" class="alert alert-error">
+ <div th:each="error : ${errors}" th:text="${error}">
+ </div>
+ </div>
+ <div th:unless="${!errors.isEmpty()}">
+ <h2 align="center">Buy confirm</h2>
+ <h2>Order information:</h2>
+ <table class="table">
+ <thead>
+ <tr>
+ <th>
+ QTY
+ </th>
+ <th>
+ Product
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr th:each="line : ${results.cart.shoppingCartLines}">
+ <td th:text="${line.sclQty}">
+ </td>
+ <td>
+ Title: <i th:text="${line.item.ITitle}"></i> - Backing:
+ <span th:text="${line.item.IBacking}"></span><br />
+ SRP. $<span th:text="${line.item.ISrp}"></span>
+ <span style="color: red;"><strong>Your Price: <span th:text="${line.item.ICost}"></span></strong></span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <h2>Your order has been processed</h2>
+ <div class="pull-left myLabel">
+ Subtotal with discount:
+ </div>
+ <div class="pull-left content" th:text="${scSubTotal}">
+ </div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">
+ Tax (8.25%):
+ </div>
+ <div class="pull-left content" th:text="${scTax}">
+ </div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">
+ Shipping and Handling:
+ </div>
+ <div class="pull-left content" th:text="${scShipCost}">
+ </div>
+ <div class="clearfix"></div>
+ <div class="pull-left myLabel">
+ Total:
+ </div>
+ <div class="pull-left content" th:text="${scTotal}">
+ </div>
+ <div class="clearfix"></div>
+ <h2>Order Number: <span th:text="${results.order.OId}"></span></h2>
+ <h1>Thank you for shopping at TPC-W</h1>
+ </div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/customer-registration.html b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/customer-registration.html
new file mode 100644
index 0000000..d15b5ee
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/customer-registration.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+ layout:decorator="/templates/layout">
+ <head>
+ <title>Customer registration</title>
+ </head>
+<body>
+<div layout:fragment="content">
+
+ <h2 align="center">Customer registration</h2>
+ <form th:action="@{'/buy;jsessionid=' + ${sessionId}}" method="get">
+ <div>
+ <label class="radio">
+ <input type="radio" name="RETURNING_FLAG" value="Y" checked="checked" />I am existing user
+ </label>
+ </div>
+ <div>
+ <label class="radio">
+ <input type="radio" name="RETURNING_FLAG" value="N" />I am a first time customer
+ </label>
+ </div>
+ <hr />
+ <div>
+ <strong>If you are an existing customer, enter your username and password:</strong><br/>
+ <br />
+ <fieldset>
+ <label>
+ Username:
+ </label>
+ <input name="username" type="text" />
+ <label>
+ Password:
+ </label>
+ <input name="password" type="password" />
+ </fieldset>
+ </div>
+ <hr />
+ <div>
+ <strong>If you are a first time customer, enter the details below:</strong><br />
+ <br />
+ <fieldset>
+ <label>Enter your birth date (mm/dd/yyyy):</label>
+ <input name="birthdate" />
+ <label>Enter your first name: </label>
+ <input name="fname" />
+ <label>Enter your last name: </label>
+ <input name="lname" />
+ <label>
+ Enter your address 1:
+ </label>
+ <input name="street1" />
+ <label>
+ Enter your address 2:
+ </label>
+ <input name="street2" />
+ <label>
+ Enter your City, State, Zip:
+ </label>
+ <input name="city" placeholder="City" />
+ <input name="state" placeholder="State" />
+ <input name="zip" placeholder="Zip" />
+ <label>
+ Enter your Country:
+ </label>
+ <input name="country" />
+ <label>
+ Enter your Phone:
+ </label>
+ <input name="phone" />
+ <label>
+ Enter your Email:
+ </label>
+ <input name="email" />
+ <label>
+ Special Instructions:
+ </label>
+ <textarea name="data" rows="4" cols="65"></textarea>
+ <input th:if="${customerId}" type="hidden" th:value="${customerId}" name="C_ID" />
+ <input th:if="${shoppingId}" type="hidden" th:value="${shoppingId}" name="SHOPPING_ID" />
+ </fieldset>
+ </div>
+ <center><input type="submit" value="Submit" class="btn" /></center>
+ </form>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/home.html b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/home.html
new file mode 100644
index 0000000..607ae5b
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/home.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+ layout:decorator="/templates/layout">
+ <head>
+ <title>TPC-W</title>
+ </head>
+<body>
+<div layout:fragment="content">
+ <div class="jumbotron">
+ <h1>TPC Web Commerce Benchmark (TPC-W)</h1>
+ </div>
+<!-- <div th:text="${welcomeMessage}"> -->
+<!-- </div> -->
+ <div class="promotional">
+ <div class="pull-left" th:each="item : ${promotional}">
+ <a th:href="@{'/product-detail?I_ID=' + ${item.IId} + '' + ${productUrl}}">
+ <img th:src="@{ ${imgResourceUrl} + '/' + ${item.IThumbnail}}" src="" width="100" height="100" />
+ </a>
+ </div>
+ <div class="clearfix"></div>
+ </div>
+
+ <hr />
+
+ <div class="categories">
+ <div>
+ <div class="pull-left" style="width: 340px; text-align: center;">
+ <h3>What's new</h3>
+ </div>
+ <div class="pull-right" style="width: 260px; text-align: center;">
+ <h3>Best sellers</h3>
+ </div>
+ <div class="clearfix"></div>
+ </div>
+ <div>
+ <div class="pull-left left-column">
+ <table>
+ <tr th:each="category : ${categories}">
+ <td>
+ <a th:text="${category.left}" th:href="@{'/new-products?SUBJECT=' + ${category.leftUrl}}"></a>
+ </td>
+ <td>
+ <a th:text="${category.right}" th:href="@{'/new-products?SUBJECT=' + ${category.rightUrl}}"></a>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div class="pull-right right-column">
+ <table>
+ <tr th:each="category : ${categories}">
+ <td>
+ <a th:text="${category.left}" th:href="@{'/best-sellers?SUBJECT=' + ${category.leftUrl}}"></a>
+ </td>
+ <td>
+ <a th:text="${category.right}" th:href="@{'/best-sellers?SUBJECT=' + ${category.rightUrl}}"></a>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div class="clearfix"></div>
+ </div>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/login.html b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/login.html
new file mode 100644
index 0000000..f43ff9a
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/login.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring3-3.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:th="http://www.thymeleaf.org">
+<head>
+ <title>Order inquiry</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <link rel="stylesheet" href="" th:href="@{/resources/css/bootstrap.min.css}"/>
+ <link rel="stylesheet" href="" th:href="@{/resources/css/bootstrap-responsive.min.css}"/>
+ <style type="text/css">
+ body {
+ padding-top: 20px;
+ padding-bottom: 40px;
+ }
+
+ /* Custom container */
+ .container-narrow {
+ margin: 0 auto;
+ max-width: 700px;
+ }
+ .container-narrow > hr {
+ margin: 30px 0;
+ }
+
+ /* Main marketing message and sign up button */
+ .jumbotron {
+ margin: 60px 0;
+ text-align: center;
+ }
+ .jumbotron h1 {
+ font-size: 72px;
+ line-height: 1;
+ }
+ .jumbotron .btn {
+ font-size: 21px;
+ padding: 14px 24px;
+ }
+
+ /* Supporting marketing content */
+ .marketing {
+ margin: 60px 0;
+ }
+ .marketing p + h4 {
+ margin-top: 28px;
+ }
+ .promotional{
+ margin: auto;
+ width: 550px;
+ }
+ .promotional .pull-left{
+ padding-right: 10px;
+ }
+ .left-column table td,
+ .right-column table td{
+ width: 150px;
+ text-align: center;
+ }
+ </style>
+</head>
+<body>
+<div class="container-narrow">
+
+ <div class="masthead">
+ <ul class="nav nav-pills pull-right">
+ <li><a href="#">Search</a></li>
+ <li><a href="#">Shopping cart</a></li>
+ <li><a href="#">Order list</a></li>
+ </ul>
+ <h3 class="muted"><a href="/" th:href="@{/}"><img th:src="@{/resources/img/logo-CloudScale.png}" /></a></h3>
+ </div>
+
+ <hr />
+ <div th:if="${errors}" class="alert alert-error">
+ <div th:each="error : ${errors}" th:text="${error}"></div>
+ </div>
+ <form action="#" th:action="@{/login}" method="post">
+ <input type="hidden" th:value="${referer}" name="referer" />
+ <fieldset>
+ <label>
+ Username:
+ </label>
+ <input name="username" type="text" />
+ <label>
+ Password:
+ </label>
+ <input name="password" type="password" />
+ <label></label>
+ <input class="btn" type="submit" value="Submit" />
+ </fieldset>
+ </form>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/new-products.html b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/new-products.html
new file mode 100644
index 0000000..cad7890
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/new-products.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+ layout:decorator="/templates/layout">
+ <head>
+ <title>New products</title>
+ </head>
+<body>
+<div layout:fragment="content">
+
+ <div class="jumbotron">
+ <h1>TPC Web Commerce Benchmark (TPC-W)</h1>
+ </div>
+ <div class="promotional">
+ <div class="pull-left" th:each="item : ${promotional}">
+ <a th:href="@{'/product-detail?I_ID=' + ${item.IId} + '' + ${productUrl}}">
+ <img th:src="@{${imgResourceUrl}} + '/' + ${item.IThumbnail}" src="" width="100" height="100" />
+ </a>
+ </div>
+ <div class="clearfix"></div>
+ </div>
+
+ <hr />
+
+ <table>
+ <thead>
+ <tr>
+ <th style="width: 50px; font-weight: bold;">
+ #
+ </th>
+ <th>
+ Author
+ </th>
+ <th>
+ Title
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr th:each="item, count : ${products}">
+ <td style="width: 50px; font-weight: bold;" th:text="${count.count}"></td>
+ <td th:text="${item.author.AFname + ' ' + item.author.ALname}">
+ </td>
+ <td>
+ <a th:href="@{'/product-detail?I_ID=' + ${item.IId}} + ${productUrl}" th:text="${item.ITitle}"></a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+ <div class="footer">
+ </div>
+</div>
+</body>
+</html>
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/order-display.html b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/order-display.html
new file mode 100644
index 0000000..816aa1b
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/order-display.html
@@ -0,0 +1,112 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+ layout:decorator="/templates/layout">
+ <head>
+ <title>Order display</title>
+ </head>
+<body>
+<div layout:fragment="content">
+ <div class="alert alert-error" th:if="${!errors.isEmpty()}" th:each="erro : ${errors}">
+ <div th:text="${err}"></div>
+ </div>
+ <div th:unless="${!errors.isEmpty()}">
+ <div th:if="${order}">
+ <p>
+ <strong>Order ID:</strong><span th:text="${order.OId}"></span>
+ </p>
+ <p>
+ <strong>Order Placed on:</strong>
+ <span th:text="${order.ODate}"></span>
+ </p>
+ <p>
+ <strong>Shipping Type:</strong>
+ <span th:text="${order.OShipType}"></span>
+ </p>
+ <p>
+ <strong>Ship date:</strong>
+ <span th:text="${order.OShipDate}"></span>
+ </p>
+ <p>
+ <strong>Order subtotal:</strong>
+ <span th:text="${order.OSubTotal}"></span>
+ </p>
+ <p>
+ <strong>Order Tax:</strong>
+ <span th:text="${order.OTax}"></span>
+ </p>
+ <p>
+ <strong>Order Total:</strong>
+ <span th:text="${order.OTotal}"></span>
+ </p>
+
+ <div class="pull-left" style="width: 400px">
+ <strong>
+ Bill To:<br/>
+ <span th:text="${order.customer.CFname} + ' ' + ${order.customer.CLname}"></span><br />
+ </strong>
+ <br />
+ <address>
+ <span th:text="${order.addressByOShipAddrId.addrStreet1}"></span><br />
+ <span th:text="${order.addressByOShipAddrId.addrStreet2}"></span><br />
+ <span th:text="${order.addressByOShipAddrId.addrState} + ' ' + ${order.addressByOShipAddrId.addrZip}"></span><br />
+ <span th:text="${order.addressByOShipAddrId.country.coName}"></span>
+ </address>
+ <br />
+ Email: <span th:text="${order.customer.CEmail}"></span><br/>
+ Phone: <span th:text=" ${order.customer.CPhone}"></span><br/>
+ <br />
+ Order status: <span th:text="${order.OStatus}"></span><br />
+ </div>
+ <div class="pull-left">
+ <strong>
+ Ship to:
+ </strong><br />
+ <br />
+ <address>
+ <span th:text="${order.addressByOBillAddrId.addrStreet1}"></span><br />
+ <span th:text="${order.addressByOBillAddrId.addrStreet2}"></span><br />
+ <span th:text="${order.addressByOBillAddrId.addrState} + ' ' + ${order.addressByOBillAddrId.addrZip}"></span><br />
+ <span th:text="${order.addressByOBillAddrId.country.coName}"></span><br />
+ </address>
+ </div>
+
+ <table class="table">
+ <thead>
+ <tr>
+ <th>
+ Item #
+ </th>
+ <th>
+ Title
+ </th>
+ <th>
+ Cost
+ </th>
+ <th>
+ QTY
+ </th>
+ <th>
+ Discount
+ </th>
+ <th>
+ Comment
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr th:each="o : ${orderLines}">
+ <td th:text="${o.olId}"></td>
+ <td th:text="${o.item.ITitle}"></td>
+ <td th:text="${o.item.ICost}"></td>
+ <td th:text="${o.olQty}"></td>
+ <td th:text="${o.olDiscount}"></td>
+ <td th:text="${o.olComment}"></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/order-inquiry.html b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/order-inquiry.html
new file mode 100644
index 0000000..92c91cf
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/order-inquiry.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+ layout:decorator="/templates/layout">
+ <head>
+ <title>Order inquiry</title>
+ </head>
+<body>
+<div layout:fragment="content">
+ <div>
+ <form th:action="@{/order-display}" method="get" >
+ <fieldset>
+ <label>
+ Username:
+ </label>
+ <input name="username" type="text" />
+ <label>
+ Password:
+ </label>
+ <input name="password" type="password" />
+ <label></label>
+ <div th:if="${shoppingId}" >
+ <input type="hidden" name="SHOPPING_ID" th:value="${shoppingId}" />
+ </div>
+ <div th:if="${customerId}">
+ <input type="hidden" name="C_ID" th:value="${customerId}" />
+ </div>
+ <input class="btn" type="submit" value="Display last order" />
+ </fieldset>
+ </form>
+ </div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/product_detail.html b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/product_detail.html
new file mode 100644
index 0000000..dfc38fb
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/product_detail.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+ layout:decorator="/templates/layout">
+ <head>
+ <title>Product detail page</title>
+ </head>
+<body>
+<div layout:fragment="content">
+
+ <div class="row-fluid marketing">
+ <dl class="dl-horizontal">
+ <dt>Title</dt>
+ <dd th:text="${item.ITitle}">Title</dd>
+
+ <dt>Author</dt>
+ <dd th:text="${item.author.AFname + ' ' + item.author.ALname}">FirstName LastName</dd>
+
+ <dt>Subject</dt>
+ <dd th:text="${item.ISubject}">Subject</dd>
+
+ <dt>Description</dt>
+ <dd th:text="${item.IDesc}">Description</dd>
+
+ <dt>Suggested Retail Price</dt>
+ <dd th:text="${item.ISrp}">Suggested Retail Price</dd>
+
+ <dt>Our Price</dt>
+ <dd th:text="${item.ICost}">Our Price</dd>
+
+ <dt>You save</dt>
+ <dd th:with="savings=(${item.ISrp} - ${item.ICost})"
+ th:text="${#strings.indexOf(savings, '.') == -1} ? ${savings} : ${#strings.substring(savings, 0, #strings.indexOf(savings, '.')+3)}">You save</dd>
+
+ <dt>Backing</dt>
+ <dd><span th:text="${item.IBacking}">Item Backing</span><span th:text="${item.IPage}">Item page</span></dd>
+
+ <dt>Published by</dt>
+ <dd th:text="${item.IPublisher}">Publisher</dd>
+
+ <dt>Publication date</dt>
+ <dd th:text="${item.IPubDate}">Pub date</dd>
+
+ <dt>Avail date</dt>
+ <dd th:text="${item.IAvail}">Avail date</dd>
+
+ <dt>Dimensions</dt>
+ <dd th:text="${item.IDimension}">Dimensions</dd>
+
+ <dt>ISBN</dt>
+ <dd th:text="${item.IIsbn}">ISBN</dd>
+ </dl>
+ </div>
+ <div>
+ <a class="btn" th:href="@{${addToShoppingCartUrl}}">Add to cart</a>
+ <a class="btn" href="#">Update</a>
+
+ </div>
+ </div>
+</body>
+</html>
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/search.html b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/search.html
new file mode 100644
index 0000000..b412687
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/search.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+ layout:decorator="/templates/layout">
+ <head>
+ <title>Search</title>
+ </head>
+<body>
+<div layout:fragment="content">
+
+ <div class="jumbotron">
+ <h1>TPC Web Commerce Benchmark (TPC-W)</h1>
+ </div>
+ <div class="promotional">
+ <div class="pull-left" th:each="item : ${promotional}">
+ <a th:href="@{'/product-detail?I_ID=' + ${item.IId} + '' + ${productUrl}}">
+ <img th:src="@{ ${imgResourceUrl} + '/' + ${item.IThumbnail}" src="" width="100" height="100" />
+
+ </a>
+ </div>
+ <div class="clearfix"></div>
+ </div>
+
+ <hr />
+
+ <form method="get">
+ Search by:
+ <select name="searchField">
+ <option value="author">
+ Author
+ </option>
+ <option value="title">
+ Title
+ </option>
+ <option value="subject">
+ Subject
+ </option>
+ </select>
+ <input type="text" name="keyword" th:value="${keyword}"/>
+ <input type="submit" value="Submit"/>
+ </form>
+ <div th:if="${results != null and not results.isEmpty()}" class="search-results">
+ <table>
+ <thead>
+ <tr>
+ <th style="width: 50px; font-weight: bold;">
+ #
+ </th>
+ <th>
+ Author
+ </th>
+ <th>
+ Title
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr th:each="item, count : ${results}">
+ <td style="width: 50px; font-weight: bold;" th:text="${count.count}"></td>
+ <td th:text="${item.author.AFname + ' ' + item.author.ALname}">
+ </td>
+ <td>
+ <a th:href="@{'/product-detail?I_ID=' + ${item.IId}} + ${productUrl}" th:text="${item.ITitle}"></a>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <div th:unless="${ results != null and not results.isEmpty()}">
+ No results!
+ </div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/shopping-cart.html b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/shopping-cart.html
new file mode 100644
index 0000000..751cae9
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/shopping-cart.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+ layout:decorator="/templates/layout">
+ <head>
+ <title>Shopping cart</title>
+ </head>
+<body>
+<div layout:fragment="content">
+ <div th:if="${errors.isEmpty()}">
+ <div class="jumbotron">
+ <h1>TPC Web Commerce Benchmark (TPC-W)</h1>
+ </div>
+ <div class="promotional">
+ <div class="pull-left" th:each="item : ${promotional}">
+ <a th:href="@{'/product-detail?I_ID=' + ${item.IId}}">
+ <img th:src="@{ ${imgResourceUrl} + '/' + ${item.IThumbnail}" src="" width="100" height="100" />
+ </a>
+ </div>
+ <div class="clearfix"></div>
+ </div>
+
+ <hr />
+ <div th:if="${cart.shoppingCartLines != null}">
+ <form action="" method="get">
+ <table class="table">
+ <thead>
+ <tr>
+ <th>
+ QTY
+ </th>
+ <th>
+ Product
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr th:each="line, i : ${cart.shoppingCartLines}">
+ <td>
+ <input type="hidden" th:name="'I_ID_' + ${i.index}" th:value="${line.item.IId}" />
+ <input th:name="'QTY_' + ${i.index}" size="3" th:value="${line.sclQty}" />
+ </td>
+ <td>
+ Title: <i th:text="${line.item.ITitle}"></i> - Backing:
+ <span th:text="${line.item.IBacking}"></span><br />
+ SRP. $<span th:text="${line.item.ISrp}"></span>
+ <span style="color: red;"><strong>Your Price: <span th:text="${line.item.ICost}"></span></strong></span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <strong>Subtotal: <span th:text="${subTotal}"></span></strong>
+ <div style="text-align: center">
+ <a class="btn" th:href="@{${checkoutUrl}}">Checkout</a>
+ <a class="btn" th:href="@{${homeUrl}}">Home</a>
+ </div>
+ <p style="text-align:center">
+ If you have changed the quantities and/or taken anything out<br />
+ of your shopping cart, click here to refresh your shopping cart:
+ </p>
+ <input type="hidden" name="ADD_FLAG" value="N" />
+ <input type="hidden" name="SHOPPING_ID" th:value="${cart.scId}" />
+ <input th:if="${customerId}" type="hidden" name="C_ID" th:value="${customerId}"/>
+ <input type="submit" value="Update" class="btn" />
+ </form>
+ </div>
+ <div th:unless="${cart.shoppingCartLines != null}">
+ Empty cart!
+ </div>
+
+ </div>
+ <div th:unless="${errors.isEmpty()}">
+ <div class="alert alert-error">
+ <div th:each="error : ${errors}" th:text="error"></div>
+ </div>
+ </div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/templates/layout.html b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/templates/layout.html
new file mode 100644
index 0000000..6f0319e
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/views/templates/layout.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring3-3.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:th="http://www.thymeleaf.org">
+<head>
+ <title>TPC-W</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <link rel="stylesheet" href="" th:href="@{${cssResourceUrl} + '/bootstrap.min.css' }"/>
+ <link rel="stylesheet" href="" th:href="@{${cssResourceUrl} + '/bootstrap-responsive.min.css'}"/>
+ <style type="text/css">
+ body {
+ padding-top: 20px;
+ padding-bottom: 40px;
+ }
+
+ /* Custom container */
+ .container-narrow {
+ margin: 0 auto;
+ max-width: 700px;
+ }
+ .container-narrow > hr {
+ margin: 30px 0;
+ }
+
+ /* Main marketing message and sign up button */
+ .jumbotron {
+ margin: 60px 0;
+ text-align: center;
+ }
+ .jumbotron h1 {
+ font-size: 72px;
+ line-height: 1;
+ }
+ .jumbotron .btn {
+ font-size: 21px;
+ padding: 14px 24px;
+ }
+
+ /* Supporting marketing content */
+ .marketing {
+ margin: 60px 0;
+ }
+ .marketing p + h4 {
+ margin-top: 28px;
+ }
+ .promotional{
+ margin: auto;
+ width: 550px;
+ }
+ .promotional .pull-left{
+ padding-right: 10px;
+ }
+ .left-column table td,
+ .right-column table td{
+ width: 150px;
+ text-align: center;
+ }
+
+ .footer{
+ padding: 6px;
+ text-align: center;
+ }
+ </style>
+</head>
+<body>
+<div class="container-narrow">
+
+ <div class="masthead">
+ <ul class="nav nav-pills pull-right">
+ <li><a th:href="@{${searchUrl}}">Search</a></li>
+ <li><a th:href="@{${shoppingCartUrl}}">Shopping cart</a></li>
+ <li><a th:href="@{${orderInquiryUrl}}">Order list</a></li>
+ </ul>
+ <h3 class="muted"><a href="/" th:href="@{/}"><img th:src="@{${imgResourceUrl} + '/logo-CloudScale-aws.png'}" /></a></h3>
+ </div>
+
+ <hr />
+ <div layout:fragment="content"></div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/web.xml b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..9a82c6e
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>/WEB-INF/spring/root-context.xml</param-value>
+ </context-param>
+ <listener>
+ <listener-class>org.apache.logging.log4j.core.web.Log4jServletContextListener</listener-class>
+ </listener>
+ <listener>
+ <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+ </listener>
+ <servlet>
+ <servlet-name>appServlet</servlet-name>
+ <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+ <init-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>appServlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+ <filter>
+ <filter-name>log4jServletFilter</filter-name>
+ <filter-class>org.apache.logging.log4j.core.web.Log4jServletFilter</filter-class>
+ </filter>
+ <filter-mapping>
+ <filter-name>log4jServletFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ <dispatcher>REQUEST</dispatcher>
+ <dispatcher>FORWARD</dispatcher>
+ <dispatcher>INCLUDE</dispatcher>
+ <dispatcher>ERROR</dispatcher>
+ </filter-mapping>
+</web-app>
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/generator/src/test/resources/log4j.xml b/cloudscale/deployment_scripts/scripts/platform/generator/src/test/resources/log4j.xml
new file mode 100644
index 0000000..b424beb
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/generator/src/test/resources/log4j.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+ <!-- Appenders -->
+ <appender name="console" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.out" />
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%-5p: %c - %m%n" />
+ </layout>
+ </appender>
+
+ <!-- Application Loggers -->
+ <logger name="eu.cloudscale.showcase">
+ <level value="info" />
+ </logger>
+
+ <!-- 3rdparty Loggers -->
+ <logger name="org.springframework.core">
+ <level value="info" />
+ </logger>
+
+ <logger name="org.springframework.beans">
+ <level value="info" />
+ </logger>
+
+ <logger name="org.springframework.context">
+ <level value="info" />
+ </logger>
+
+ <logger name="org.springframework.web">
+ <level value="info" />
+ </logger>
+
+ <!-- Root Logger -->
+ <root>
+ <priority value="info" />
+ <appender-ref ref="console" />
+ </root>
+
+</log4j:configuration>
diff --git a/cloudscale/deployment_scripts/scripts/platform/mpm_worker.conf b/cloudscale/deployment_scripts/scripts/platform/mpm_worker.conf
new file mode 100644
index 0000000..4404ae0
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/mpm_worker.conf
@@ -0,0 +1,34 @@
+# worker MPM
+# StartServers: initial number of server processes to start
+# MinSpareThreads: minimum number of worker threads which are kept spare
+# MaxSpareThreads: maximum number of worker threads which are kept spare
+# ThreadLimit: ThreadsPerChild can be changed to this maximum value during a
+# graceful restart. ThreadLimit can only be changed by stopping
+# and starting Apache.
+# ThreadsPerChild: constant number of worker threads in each server process
+# MaxRequestWorkers: maximum number of threads
+# MaxConnectionsPerChild: maximum number of requests a server process serves
+
+# 8000 concurrent users
+<IfModule mpm_worker_module>
+ ServerLimit 250
+ StartServers 2
+ MinSpareThreads 25
+ MaxSpareThreads 100
+ ThreadLimit 50
+ ThreadsPerChild 50
+ MaxClients 1000
+ MaxRequestsPerChild 1000
+</IfModule>
+
+#<IfModule mpm_worker_module>
+# StartServers 2
+# MinSpareThreads 25
+# MaxSpareThreads 75
+# ThreadLimit 64
+# ThreadsPerChild 25
+# MaxRequestWorkers 150
+# MaxConnectionsPerChild 0
+#</IfModule>
+
+# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
diff --git a/cloudscale/deployment_scripts/scripts/platform/openstack/__init__.py b/cloudscale/deployment_scripts/scripts/platform/openstack/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/openstack/__init__.py
diff --git a/cloudscale/deployment_scripts/scripts/platform/openstack/configure-mongodb.py b/cloudscale/deployment_scripts/scripts/platform/openstack/configure-mongodb.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/openstack/configure-mongodb.py
diff --git a/cloudscale/deployment_scripts/scripts/platform/openstack/configure-mysql.py b/cloudscale/deployment_scripts/scripts/platform/openstack/configure-mysql.py
new file mode 100644
index 0000000..0cf60de
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/openstack/configure-mysql.py
@@ -0,0 +1,23 @@
+import novaclient.v2.client as novaclient
+import sys
+from cloudscale.deployment_scripts.scripts import check_args, get_cfg_logger
+
+
+class ConfigureMySQL:
+
+ def __init__(self, cfg):
+ self.cfg = cfg
+ self.user = cfg.get('OPENSTACK', 'username')
+ self.pwd = cfg.get('OPENSTACK', 'password')
+ self.url = cfg.get('OPENSTACK', 'auth_url')
+ self.tenant = cfg.get('OPENSTACK', 'tenant_name')
+
+ self.create_master()
+
+ def create_master(self):
+ pass
+
+if __name__ == '__main__':
+ check_args(2, "<output_dir> <config_path>")
+ path, cfg, logger = get_cfg_logger(sys.argv[1], sys.argv[2])
+ ConfigureMySQL(cfg)
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/platform/server.xml b/cloudscale/deployment_scripts/scripts/platform/server.xml
new file mode 100644
index 0000000..f531931
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/platform/server.xml
@@ -0,0 +1,149 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+ 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.
+-->
+<!-- Note: A "Server" is not itself a "Container", so you may not
+ define subcomponents such as "Valves" at this level.
+ Documentation at /docs/config/server.html
+ -->
+<Server port="8005" shutdown="SHUTDOWN">
+ <!-- Security listener. Documentation at /docs/config/listeners.html
+ <Listener className="org.apache.catalina.security.SecurityListener" />
+ -->
+ <!--APR library loader. Documentation at /docs/apr.html -->
+ <!--
+ <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
+ -->
+ <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
+ <Listener className="org.apache.catalina.core.JasperListener" />
+ <!-- Prevent memory leaks due to use of particular java/javax APIs-->
+ <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
+ <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
+ <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
+
+ <!-- Global JNDI resources
+ Documentation at /docs/jndi-resources-howto.html
+ -->
+ <GlobalNamingResources>
+ <!-- Editable user database that can also be used by
+ UserDatabaseRealm to authenticate users
+ -->
+ <Resource name="UserDatabase" auth="Container"
+ type="org.apache.catalina.UserDatabase"
+ description="User database that can be updated and saved"
+ factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
+ pathname="conf/tomcat-users.xml" />
+ </GlobalNamingResources>
+
+ <!-- A "Service" is a collection of one or more "Connectors" that share
+ a single "Container" Note: A "Service" is not itself a "Container",
+ so you may not define subcomponents such as "Valves" at this level.
+ Documentation at /docs/config/service.html
+ -->
+ <Service name="Catalina">
+
+ <!--The connectors can use a shared executor, you can define one or more named thread pools-->
+ <!--
+ <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
+ maxThreads="150" minSpareThreads="4"/>
+ -->
+
+
+ <!-- A "Connector" represents an endpoint by which requests are received
+ and responses are returned. Documentation at :
+ Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
+ Java AJP Connector: /docs/config/ajp.html
+ APR (HTTP/AJP) Connector: /docs/apr.html
+ Define a non-SSL HTTP/1.1 Connector on port 8080
+ -->
+ <Connector port="8080" protocol="HTTP/1.1"
+ connectionTimeout="20000"
+ URIEncoding="UTF-8"
+ maxThreads="2000"
+ acceptCount="1000"
+ redirectPort="8443" />
+ <!-- A "Connector" using the shared thread pool-->
+ <!--
+ <Connector executor="tomcatThreadPool"
+ port="8080" protocol="HTTP/1.1"
+ connectionTimeout="20000"
+ redirectPort="8443" />
+ -->
+ <!-- Define a SSL HTTP/1.1 Connector on port 8443
+ This connector uses the JSSE configuration, when using APR, the
+ connector should be using the OpenSSL style configuration
+ described in the APR documentation -->
+ <!--
+ <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
+ maxThreads="150" scheme="https" secure="true"
+ clientAuth="false" sslProtocol="TLS" />
+ -->
+
+ <!-- Define an AJP 1.3 Connector on port 8009 -->
+ <!--
+ <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
+ -->
+
+
+ <!-- An Engine represents the entry point (within Catalina) that processes
+ every request. The Engine implementation for Tomcat stand alone
+ analyzes the HTTP headers included with the request, and passes them
+ on to the appropriate Host (virtual host).
+ Documentation at /docs/config/engine.html -->
+
+ <!-- You should set jvmRoute to support load-balancing via AJP ie :
+ <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
+ -->
+ <Engine name="Catalina" defaultHost="localhost">
+
+ <!--For clustering, please take a look at documentation at:
+ /docs/cluster-howto.html (simple how to)
+ /docs/config/cluster.html (reference documentation) -->
+ <!--
+ <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
+ -->
+
+ <!-- Use the LockOutRealm to prevent attempts to guess user passwords
+ via a brute-force attack -->
+ <Realm className="org.apache.catalina.realm.LockOutRealm">
+ <!-- This Realm uses the UserDatabase configured in the global JNDI
+ resources under the key "UserDatabase". Any edits
+ that are performed against this UserDatabase are immediately
+ available for use by the Realm. -->
+ <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
+ resourceName="UserDatabase"/>
+ </Realm>
+
+ <Host name="localhost" appBase="webapps"
+ unpackWARs="true" autoDeploy="true">
+
+ <!-- SingleSignOn valve, share authentication between web applications
+ Documentation at: /docs/config/valve.html -->
+ <!--
+ <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
+ -->
+
+ <!-- Access log processes all example.
+ Documentation at: /docs/config/valve.html
+ Note: The pattern used is equivalent to using pattern="common" -->
+ <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
+ prefix="localhost_access_log." suffix=".txt"
+ pattern="%h %l %u %t "%r" %s %b" />
+
+ </Host>
+ </Engine>
+ </Service>
+</Server>
diff --git a/cloudscale/deployment_scripts/scripts/software/__init__.py b/cloudscale/deployment_scripts/scripts/software/__init__.py
new file mode 100644
index 0000000..8f76346
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/__init__.py
@@ -0,0 +1 @@
+__author__ = 'ivansek'
diff --git a/cloudscale/deployment_scripts/scripts/software/check-running-showcase_instances.py b/cloudscale/deployment_scripts/scripts/software/check-running-showcase_instances.py
new file mode 100644
index 0000000..231d6c0
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/check-running-showcase_instances.py
@@ -0,0 +1,78 @@
+import subprocess
+from novaclient.v1_1 import client as novaclient
+import time
+import boto
+
+
+def read_config(config_file):
+ cfg = boto.Config()
+ cfg.load_from_path(config_file)
+ return cfg
+
+
+class Checker:
+ def __init__(self):
+ self.cfg = read_config('config.ini')
+
+ self.user = self.cfg.get('OPENSTACK', 'username')
+ self.pwd = self.cfg.get('OPENSTACK', 'password')
+ self.url = self.cfg.get('OPENSTACK', 'auth_url')
+ self.tenant = self.cfg.get('OPENSTACK', 'tenant_name')
+
+ self.nc = novaclient.Client(self.user, self.pwd, self.tenant, auth_url=self.url)
+
+ self.showcase_server_ips = []
+
+ while True:
+ self.check()
+ time.sleep(5)
+
+ def get_ip(self, server):
+ for address in server.addresses['private']:
+ if address['OS-EXT-IPS:type'] == 'fixed':
+ server_ip = address['addr']
+ break
+ else:
+ server_ip = None
+ print "Error: can not get IP address of this server"
+ return server_ip
+
+ def check(self):
+ running_server_ips = []
+ new_server_ips = []
+
+ servers = self.nc.servers.findall(name='cloudscale-sc')
+ ps = {}
+ for server in servers:
+ if server.status == 'ACTIVE':
+ server_ip = self.get_ip(server)
+ if server_ip in self.showcase_server_ips:
+ running_server_ips.append(server_ip)
+ else:
+ new_server_ips.append(server_ip)
+ ps[server_ip] = subprocess.Popen('curl -I --silent %s > /dev/null' % server_ip, shell=True)
+ for server_ip in new_server_ips:
+ ps[server_ip].wait()
+ if ps[server_ip].returncode == 0:
+ running_server_ips.append(server_ip)
+
+ if not set(self.showcase_server_ips) == set(running_server_ips):
+ self.showcase_server_ips = running_server_ips
+ self.update_config()
+ self.reload_haproxy()
+
+ def update_config(self):
+ ha_proxy_config = open('/etc/haproxy/haproxy.cfg_NO_SERVERS', 'r').read()
+ for server_ip in self.showcase_server_ips:
+ ha_proxy_config += """
+ server %s %s:80 check""" % (server_ip, server_ip)
+ open('/etc/haproxy/haproxy.cfg', 'w').write(ha_proxy_config)
+
+ def reload_haproxy(self):
+ print "config changed... reloading haproxy"
+ ps = subprocess.Popen('service haproxy reload', shell=True)
+ ps.wait()
+
+
+if __name__ == '__main__':
+ checker = Checker()
diff --git a/cloudscale/deployment_scripts/scripts/software/cloudscale-apache-virtualhost.conf b/cloudscale/deployment_scripts/scripts/software/cloudscale-apache-virtualhost.conf
new file mode 100644
index 0000000..f099cfd
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/cloudscale-apache-virtualhost.conf
@@ -0,0 +1,14 @@
+<VirtualHost *:80>
+ ProxyPreserveHost On
+ # showcase-1-a (MySQL)
+ ProxyPass /showcase-1-a http://localhost:8080/showcase-1-a
+ ProxyPassReverse /showcase-1-a http://localhost:8080/showcase-1-a
+
+ # showcase-1-b (noSQL)
+ ProxyPass /showcase-1-b http://localhost:8080/showcase-1-b
+ ProxyPassReverse /showcase-1-b http://localhost:8080/showcase-1-b
+
+ # showcase-0
+ ProxyPass /showcase-0 http://localhost:8080/showcase-0
+ ProxyPassReverse /showcase-0 http://localhost:8080/showcase-0
+</VirtualHost>
diff --git a/cloudscale/deployment_scripts/scripts/software/cloudscale-apache-virtualhost.conf.new b/cloudscale/deployment_scripts/scripts/software/cloudscale-apache-virtualhost.conf.new
new file mode 100644
index 0000000..103e7f2
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/cloudscale-apache-virtualhost.conf.new
@@ -0,0 +1,16 @@
+<VirtualHost *:80>
+ ServerName cloudscale-lb-1247224832.eu-west-1.elb.amazonaws.com
+
+ ProxyPreserveHost On
+ # showcase-1-a (MySQL)
+ ProxyPass /showcase-1-a http://localhost:8080/showcase-1-a
+ ProxyPassReverse /showcase-1-a http://localhost:8080/showcase-1-a
+
+ # showcase-1-b (noSQL)
+ ProxyPass /showcase-1-b http://localhost:8080/showcase-1-b
+ ProxyPassReverse /showcase-1-b http://localhost:8080/showcase-1-b
+
+ # showcase-0
+ ProxyPass /showcase-0 http://localhost:8080/showcase-0
+ ProxyPassReverse /showcase-0 http://localhost:8080/showcase-0
+</VirtualHost>
diff --git a/cloudscale/deployment_scripts/scripts/software/cloudscale-vm-setup.sh b/cloudscale/deployment_scripts/scripts/software/cloudscale-vm-setup.sh
new file mode 100644
index 0000000..94ccee6
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/cloudscale-vm-setup.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+sudo apt-get install -y zip tomcat7 apache2 openjdk-7-jdk
+echo deb http://apt.newrelic.com/debian/ newrelic non-free >> /etc/apt/sources.list.d/newrelic.list > /tmp/newrelic.list
+sudo cp /tmp/newrelic.list /etc/apt/sources.list.d/
+wget -O- https://download.newrelic.com/548C16BF.gpg
+sudo apt-key add 548C16BF.gpg
+sudo apt-get update
+sudo apt-get install newrelic-sysmond
+nrsysmond-config --set license_key=b71feb62bff6540111597c79259d1f28051af3be
+sudo /etc/init.d/newrelic-sysmond start
+sudo a2enmod proxy
+sudo cp cloudscale.conf /etc/apache2/sites-available/
+sudo a2ensite cloudscale
+sudo /etc/init.d/apache2 restart
+sudo /etc/init.d/tomcat7 restart
diff --git a/cloudscale/deployment_scripts/scripts/software/deploy_showcase.py b/cloudscale/deployment_scripts/scripts/software/deploy_showcase.py
new file mode 100644
index 0000000..f17a4e4
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/deploy_showcase.py
@@ -0,0 +1,135 @@
+import logging
+import time
+import paramiko
+import ConfigParser
+import sys, os
+import subprocess
+import requests
+import select
+from cloudscale.deployment_scripts.scripts import check_args, get_cfg_logger
+
+
+class DeploySoftware:
+
+ def __init__(self, this):
+
+ self.props = this
+
+ #self.compile()
+ self.deploy_software()
+
+ def write_db_config(self, ssh, path):
+ cfg = "jdbc.dbtype=mysql\n"
+
+ if int(self.props.db_num_instances) > 1:
+ cfg += 'jdbc.driverClassName=com.mysql.jdbc.ReplicationDriver\n'
+ cfg += 'jdbc.url=jdbc:mysql:replication://%s/%s\n' % (self.props.cfg.get('platform', 'urls'), self.props.database_name )
+ else:
+ cfg += 'jdbc.driverClassName=com.mysql.jdbc.Driver\n'
+ cfg += 'jdbc.url=jdbc:mysql://%s/%s\n' % (self.props.cfg.get('platform', 'urls'), self.props.database_name)
+
+ cfg += 'jdbc.username=%s\n' % self.props.database_user
+ cfg += 'jdbc.password=%s\n' % self.props.database_pass
+ cfg += 'jdbc.hibernate.dialect=org.hibernate.dialect.MySQLDialect\n'
+
+ _, stdout, _ = ssh.exec_command('echo "%s" | sudo tee %s' % (cfg, path))
+ self.wait_for_command(stdout)
+
+
+
+
+ # def compile(self):
+ # self.logger.log('Compiling showcase ...')
+ # cmd = 'cd ' + self.file_path + '/showcase;/usr/bin/mvn -Pamazon-hibernate -Dconnection_pool_size=' + self.config.db.get('connection_pool_size') + ' install '
+ # self.logger.log(msg=cmd, level=logging.DEBUG)
+ # #subprocess.check_output(cmd)
+ # ps = subprocess.Popen(cmd, shell=True)
+ # ps.wait()
+ # self.logger.log('Compiled')
+
+
+ def deploy_software(self):
+ for ip_address in self.props.ip_addresses:
+ if sys.platform == 'win32':
+ self.windows_shell(ip_address);
+ else:
+ self.unix_shell(ip_address)
+
+ def windows_shell(self,ip_address):
+ raise Exception('Not implemented for Windows platform!')
+
+ def unix_shell(self, ip_address):
+ try:
+ self.props.logger.log("Deploying showcase on " + ip_address)
+ self.props.logger.log("This may take a while. Please wait ...")
+ time.sleep(60)
+ paramiko.util.log_to_file('paramiko.log')
+
+ ssh = self.ssh_to_instance(ip_address)
+
+ showcase_url = str(self.props.showcase_location).replace(' ', '%20')
+ _, stdout, _ = ssh.exec_command('wget -T90 -q %s -O showcase.war' % showcase_url)
+ self.wait_for_command(stdout)
+
+ _, stdout, _ = ssh.exec_command("sudo unzip -o showcase.war -d %s" % self.props.deploy_name)
+ self.wait_for_command(stdout)
+
+ self.write_db_config(ssh, 'showcase-1-a/WEB-INF/classes/database/database.aws.hibernate.properties')
+ ssh.exec_command("sudo sed -i 's/${connection_pool_size}/%s/g' %s" % (self.props.connection_pool_size, 'showcase-1-a/WEB-INF/classes/hibernate.xml'))
+
+ _, stdout, _ = ssh.exec_command("sudo cp -r showcase-1-a /var/lib/tomcat7/webapps/")
+ self.wait_for_command(stdout)
+
+ _, stdout, _ = ssh.exec_command("sudo /etc/init.d/tomcat7 restart")
+ self.wait_for_command(stdout)
+ time.sleep(60)
+
+ # if not self.check(ip_address):
+ # ssh.exec_command("sudo /etc/init.d/tomcat7 restart")
+ ssh.close()
+ self.props.logger.log("Successfully finished installation")
+ except Exception as e:
+ raise e
+
+ def ssh_to_instance(self, ip_address):
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+
+ if self.props.key_pair:
+ ssh.connect(ip_address, username=self.props.remote_user, key_filename=self.props.key_pair)
+ else:
+ ssh.connect(ip_address, username=self.props.remote_user)
+ return ssh
+
+ def wait_for_command(self, stdout):
+ while not stdout.channel.exit_status_ready():
+ # Only print data if there is data to read in the channel
+ if stdout.channel.recv_ready():
+ rl, wl, xl = select.select([stdout.channel], [], [], 0.0)
+ if len(rl) > 0:
+ # Print data from stdout
+ self.props.logger.log(msg=stdout.channel.recv(1024), level=logging.DEBUG)
+
+
+ def check(self, ip_address):
+ r = requests.get('http://%s/showcase-1-a' % ip_address)
+ return r.status_code == 200
+
+ def parse_config_file(self, config_file):
+ f = open(config_file, 'r')
+ ip_addresses = []
+ for line in f.readlines():
+ ip_addresses.append(line)
+ return ip_addresses
+
+
+
+if __name__ == '__main__':
+ check_args(2, "<output_dir> <config_path>")
+ path, cfg, logger = get_cfg_logger(sys.argv[1], sys.argv[2])
+ class Dummy(): pass
+ obj = Dummy()
+ obj.ip_addresses = cfg.get('infrastructure', 'ip_addresses')
+ obj.db_num_instances = cfg.get('RDS', 'num_instances')
+
+ DeploySoftware(obj)
diff --git a/cloudscale/deployment_scripts/scripts/software/deploy-amazon.sh b/cloudscale/deployment_scripts/scripts/software/deploy-amazon.sh
new file mode 100755
index 0000000..e36a1f8
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/deploy-amazon.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# Author: Simon Ivansek @ Xlab
+# Email: simon.ivansek@xlab.si
+
+if [ #$ -lt 2 ]
+then
+ echo -e "Usage:\n $ deploy-amazon.sh <ip_address> <key_pair_path> "
+ exit(0)
+fi
+
+SERVER_HOST=${1}
+REMOTE_SSH_PORT=22
+REMOTE_WEBAPPS_DIR=/var/lib/tomcat7/webapps
+LOCAL_WAR_PATH=showcase/target/showcase-1.0.0-BUILD-SNAPSHOT.war
+KEYPAIR_PATH=${2}
+
+echo "########## NOTICE ###########"
+echo "For this deployment you need to have a ssh key generated. Your public key (.pub) needs"
+echo "to be authorized on remote server. How to do this see:"
+echo "http://www.dotkam.com/2009/03/10/run-commands-remotely-via-ssh-with-no-password/"
+echo ""
+echo "Is ${SERVER_HOST} on port ${REMOTE_SSH_PORT} available?"
+if ! [ "`nc -zvv ${SERVER_HOST} ${REMOTE_SSH_PORT}`" ]; then
+ echo "No. Terminating ..."
+ exit;
+else
+ echo "Yes. Contuining ..."
+fi
+
+echo "##########################"
+echo "# BUILDING MYSQL VERSION #"
+echo "##########################"
+cd showcase
+mvn -P amazon-hibernate clean install
+echo "###########################"
+echo "# DEPLOYING MYSQL VERSION #"
+echo "###########################"
+ssh -i ${KEYPAIR_PATH} ubuntu@${SERVER_HOST} "sudo /etc/init.d/tomcat7 stop"
+ssh -i ${KEYPAIR_PATH} ubuntu@${SERVER_HOST} "sudo rm -rf ${REMOTE_WEBAPPS_DIR}/showcase-1*"
+scp -i ${KEYPAIR_PATH} ${LOCAL_WAR_PATH} ubuntu@${SERVER_HOST}:${REMOTE_WEBAPPS_DIR}/showcase-1-a.war
+#ssh -i ${KEYPAIR_PATH} ubuntu@${SERVER_HOST} "sudo /etc/init.d/tomcat7 start"
+
+#echo "##########################"
+#echo "# BUILDING noSQL VERSION #"
+#echo "##########################"
+#mvn -P amazon-mongodb clean install
+#echo "###########################"
+#echo "# DEPLOYING noSQL VERSION #"
+#echo "###########################"
+#ssh -i ${KEYPAIR_PATH} ubuntu@${SERVER_HOST} "sudo /etc/init.d/tomcat7 stop"
+#scp -i ${KEYPAIR_PATH} ${LOCAL_WAR_PATH} ubuntu@${SERVER_HOST}:${REMOTE_WEBAPPS_DIR}/showcase-1-b.war
+ssh -i ${KEYPAIR_PATH} ubuntu@${SERVER_HOST} "sudo /etc/init.d/tomcat7 start"
+echo ""
+echo "Finished!"
+done
diff --git a/cloudscale/deployment_scripts/scripts/software/haproxy.cfg b/cloudscale/deployment_scripts/scripts/software/haproxy.cfg
new file mode 100644
index 0000000..5ec33bc
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/haproxy.cfg
@@ -0,0 +1,35 @@
+global
+ log 127.0.0.1 local0
+ log 127.0.0.1 local1 notice
+ #log loghost local0 info
+ maxconn 4096
+ user haproxy
+ group haproxy
+ daemon
+
+defaults
+ log global
+ mode http
+ option httplog
+ option dontlognull
+ option redispatch
+ maxconn 20000
+ contimeout 5000
+ clitimeout 50000
+ srvtimeout 50000
+
+ errorfile 400 /etc/haproxy/errors/400.http
+ errorfile 403 /etc/haproxy/errors/403.http
+ errorfile 408 /etc/haproxy/errors/408.http
+ errorfile 500 /etc/haproxy/errors/500.http
+ errorfile 502 /etc/haproxy/errors/502.http
+ errorfile 503 /etc/haproxy/errors/503.http
+ errorfile 504 /etc/haproxy/errors/504.http
+
+
+listen showcase *:80
+ option forwardfor
+ option httpchk
+ balance roundrobin
+
+ # --- SERVERS --- #
diff --git a/cloudscale/deployment_scripts/scripts/software/install-apache-tomcat.sh b/cloudscale/deployment_scripts/scripts/software/install-apache-tomcat.sh
new file mode 100644
index 0000000..477cdaa
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/install-apache-tomcat.sh
@@ -0,0 +1,36 @@
+
+echo "NOTE: installing apache tomcat"
+echo "nameserver 8.8.8.8" | sudo tee --append /etc/resolv.conf
+sudo apt-get update
+sudo apt-get install -y zip tomcat7 apache2 openjdk-7-jdk
+
+sudo sed -i 's/^securerandom.source=file:\/dev\/urandom$/securerandom.source=file\:\/dev\/.\/urandom/' /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/security/java.security
+sudo sed -i 's/^JAVA_OPTS="-Djava.awt.headless=true -Xmx128m -XX:+UseConcMarkSweepGC"$/JAVA_OPTS="-Djava.awt.headless=true -Xmx2024m -XX:+UseConcMarkSweepGC"/' /etc/default/tomcat7
+echo "NOTE: stopping apache and tomcat"
+sudo /etc/init.d/apache2 stop
+sudo /etc/init.d/tomcat7 stop
+
+echo '<VirtualHost *:80>
+ ProxyPreserveHost On
+ # showcase-1-a (MySQL)
+ ProxyPass /showcase-1-a http://localhost:8080/showcase-1-a
+ ProxyPassReverse /showcase-1-a http://localhost:8080/showcase-1-a
+
+ # showcase-1-b (noSQL)
+ ProxyPass /showcase-1-b http://localhost:8080/showcase-1-b
+ ProxyPassReverse /showcase-1-b http://localhost:8080/showcase-1-b
+
+ # showcase-0
+ ProxyPass /showcase-0 http://localhost:8080/showcase-0
+ ProxyPassReverse /showcase-0 http://localhost:8080/showcase-0
+</VirtualHost>' | sudo tee /etc/apache2/sites-available/cloudscale.conf
+
+echo "NOTE: enabling proxy and apache cloudscale configuration"
+sudo a2enmod proxy_http
+sudo a2dismod mpm_event
+sudo a2enmod mpm_worker
+sudo a2dissite 000-default
+sudo a2ensite cloudscale
+
+echo "" | sudo tee --append /etc/hosts
+echo "127.0.0.1 cloudscale-sc" | sudo tee --append /etc/hosts
diff --git a/cloudscale/deployment_scripts/scripts/software/install-load-balancer.sh b/cloudscale/deployment_scripts/scripts/software/install-load-balancer.sh
new file mode 100644
index 0000000..3343d3b
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/install-load-balancer.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+# TODO: remove this
+echo "root:root"|chpasswd
+
+
+echo "NOTE: installing load balancer and pip"
+apt-get update
+apt-get install -y haproxy python-pip
+
+pip install python-novaclient
+pip install boto
+
+echo "NOTE: enabling load balancer"
+sed -i s/'ENABLED=0'/'ENABLED=1'/ /etc/default/haproxy
+
+echo "NOTE: creating HAProxy configuration"
+cat << INCLUDE_CONFIG_FILE > /etc/haproxy/haproxy.cfg_NO_SERVERS
+#####REPLACE_ME_WITH_CONFIG#####
+INCLUDE_CONFIG_FILE
+
+cp /etc/haproxy/haproxy.cfg_NO_SERVERS /etc/haproxy/haproxy.cfg
+
+echo "NOTE: starting load balancer"
+service haproxy start
+
+
+
+base64 --decode << DECODE_ME > checker.py
+###PLACEHOLDER_FOR_checker.py###
+DECODE_ME
+
+base64 --decode << DECODE_ME > config.ini
+###PLACEHOLDER_FOR_config.ini###
+DECODE_ME
+
+
+echo "NOTE: starting script that detects showcase instances and adds them to config and reloads haproxy"
+python checker.py &
+
+
+echo "NOTE: finished"
diff --git a/cloudscale/deployment_scripts/scripts/software/install-mongodb.sh b/cloudscale/deployment_scripts/scripts/software/install-mongodb.sh
new file mode 100644
index 0000000..e16ede2
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/install-mongodb.sh
@@ -0,0 +1,32 @@
+
+# TODO: remove this
+echo "root:root"|chpasswd
+
+
+echo "NOTE: installing mongodb"
+apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
+echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | tee /etc/apt/sources.list.d/mongodb.list
+apt-get update
+
+apt-get install -y mongodb-org
+
+service mongod stop
+
+
+
+sed -i 's/bind_ip = 127.0.0.1/bind_ip = 0.0.0.0/g' /etc/mongod.conf
+# alternative port!
+sed -i 's/#port = 27017/port = 27037/g' /etc/mongod.conf
+
+
+
+echo "NOTE: adding passwordless sudo for user $USERNAME"
+echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/we-need-passwordless-sudo
+chmod 0440 /etc/sudoers.d/we-need-passwordless-sudo
+
+
+
+echo "NOTE: finished... will poweroff automatically"
+# deploy script has to detect when installation is finished
+sleep 5
+poweroff
diff --git a/cloudscale/deployment_scripts/scripts/software/install-mysql-galera.sh b/cloudscale/deployment_scripts/scripts/software/install-mysql-galera.sh
new file mode 100644
index 0000000..c12b074
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/install-mysql-galera.sh
@@ -0,0 +1,17 @@
+
+# TODO: remove this
+echo "root:root"|chpasswd
+
+
+echo "NOTE: installing mysql wsrep galera"
+apt-get update
+wget https://launchpad.net/codership-mysql/5.6/5.6.16-25.5/+download/mysql-server-wsrep-5.6.16-25.5-amd64.deb
+wget https://launchpad.net/galera/3.x/25.3.5/+download/galera-25.3.5-amd64.deb
+dpkg -i mysql-server-wsrep-5.6.16-25.5-amd64.deb galera-25.3.5-amd64.deb
+apt-get -f install -y
+
+
+echo "NOTE: creating directory for mysql logs"
+mkdir -p /var/log/mysql/
+
+
diff --git a/cloudscale/deployment_scripts/scripts/software/install-mysql-galera-import-dump.sh b/cloudscale/deployment_scripts/scripts/software/install-mysql-galera-import-dump.sh
new file mode 100644
index 0000000..06dc90f
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/install-mysql-galera-import-dump.sh
@@ -0,0 +1,53 @@
+
+echo "NOTE: starting mysql service"
+service mysql start --wsrep-new-cluster --wsrep_cluster_address="gcomm://"
+
+# wait for mysql to start
+RETRIES=100
+COUNTER=0
+false
+while [ $? -ne 0 ]
+do
+ #service mysql start
+ let COUNTER=COUNTER+1
+ if [ $COUNTER -gt $RETRIES ]
+ then
+ echo "ERROR: Could not connect to mysql server in $RETRIES tries!"
+ exit 1
+ fi
+ sleep 3
+ echo "NOTE: $COUNTER. try to connect to mysql server."
+ mysqladmin ping --host=127.0.0.1 > /dev/null 2>&1
+done
+echo "NOTE: Connected to mysql server"
+
+echo "NOTE: waiting for dump.sql to be uploaded"
+while [ ! -f /home/$USERNAME/finished ]
+do
+ sleep 2
+done
+
+sleep 5
+
+echo "NOTE: creating user and database"
+echo "create database $DB_NAME;" | mysql --host=127.0.0.1
+echo "grant all privileges on $DB_NAME.* to $DB_USERNAME@'%' identified by '$DB_PASSWORD';" | mysql --host=127.0.0.1
+
+
+echo "NOTE: importing dump file"
+mysql --host=127.0.0.1 $DB_NAME < /home/$USERNAME/dump.sql
+if [ $? -eq 0 ]
+then
+ echo "NOTE: dump imported successfully"
+else
+ echo "ERROR: dump import failed!"
+fi
+
+rm /home/$USERNAME/dump.sql
+
+
+
+echo "NOTE: finished... will poweroff automatically"
+# deploy script has to detect when installation is finished
+sleep 5
+poweroff
diff --git a/cloudscale/deployment_scripts/scripts/software/install-tomcat-apache.py b/cloudscale/deployment_scripts/scripts/software/install-tomcat-apache.py
new file mode 100644
index 0000000..a57b807
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/install-tomcat-apache.py
@@ -0,0 +1,82 @@
+
+import time
+import paramiko
+import ConfigParser
+import sys, os
+from common.Cloudscale import *
+
+class InstallTomcatApache:
+
+ def __init__(self, config_path, cfg, key_name, key_pair):
+ self.config_path = config_path
+ self.cfg = cfg
+ self.ip_addresses = self.cfg.get('infrastructure', 'ip_address').split(",")
+ self.remote_user = self.cfg.get('infrastructure', 'remote_user')
+ self.key_pair = key_pair
+ self.setup_instance()
+ self.write_config()
+
+ def setup_instance(self):
+ for ip_address in self.ip_addresses:
+ if sys.platform == 'win32':
+ self.windows_shell(ip_address)
+ else:
+ self.unix_shell(ip_address)
+
+ def windows_shell(self, ip_address):
+ raise Exception('Not implemented for Windows platform!')
+
+ def unix_shell(self, ip_address):
+ print "Installing needed software on " + ip_address
+ print "This may take a while. Please wait ..."
+ time.sleep(60)
+
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+
+
+ if key_pair:
+ ssh.connect(ip_address, username=self.remote_user, key_filename=os.path.abspath(self.key_pair))
+ else:
+ ssh.connect(ip_address, username=self.remote_user)
+
+ working_dir = str(os.path.sep).join(os.path.abspath(__file__).split(os.path.sep)[:-1])
+
+ scp = paramiko.SFTPClient.from_transport(ssh.get_transport())
+ scp.put(os.path.abspath('%s%scloudscale-vm-setup.sh' % (working_dir, os.path.sep)), 'cloudscale-vm-setup.sh')
+ scp.put(os.path.abspath('%s%scloudscale-apache-virtualhost.conf' % (working_dir, os.path.sep)), 'cloudscale.conf')
+
+ _, stdout, _ = ssh.exec_command("sudo sh cloudscale-vm-setup.sh")
+ stdout.readlines()
+ print "Successfully finished installation"
+
+ def parse_config_file(self, config_file):
+ f = open(config_file, 'r')
+ ip_addresses = []
+ for line in f.readlines():
+ ip_addresses.append(line)
+ return ip_addresses
+
+ def write_config(self):
+ self.cfg.save_option(self.config_path, 'software', 'remote_deploy_path', '/var/lib/tomcat7/webapps/')
+ self.cfg.save_option(self.config_path, 'software', 'mysql_war_path', 'showcase-1-a.war')
+ self.cfg.save_option(self.config_path, 'software', 'nosql_war_path', 'showcase-1-b.war')
+ # f = open(os.path.abspath('../software.ini'), 'w')
+ # f.write('[Cloudscale]\n')
+ # f.write('remote_user='+ self.remote_user +'\n')
+ # f.write('ip_addresses=' + ','.join(self.ip_addresses) + '\n')
+ # f.write('key_pair=' + (self.key_pair if self.key_pair else ''))
+ # f.write('remote_deploy_path=/var/lib/tomcat7/webapps/')
+ # f.write('mysql_war_path=showcase-1-a.war')
+ # f.write('nosql_war_path=showcase-1-b.war')
+ # f.close()
+
+
+if __name__ == '__main__':
+ print __file__
+ print str(os.path.sep).join(os.path.abspath(__file__).split(os.path.sep)[:-1])
+ check_args(1, "<config_path>")
+
+ config_path, cfg, key_name, key_pair = parse_args()
+
+ InstallTomcatApache(config_path, cfg, key_name, key_pair)
diff --git a/cloudscale/deployment_scripts/scripts/software/master_slave/__init__.py b/cloudscale/deployment_scripts/scripts/software/master_slave/__init__.py
new file mode 100644
index 0000000..8f76346
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/master_slave/__init__.py
@@ -0,0 +1 @@
+__author__ = 'ivansek'
diff --git a/cloudscale/deployment_scripts/scripts/software/master_slave/my.cnf.master b/cloudscale/deployment_scripts/scripts/software/master_slave/my.cnf.master
new file mode 100644
index 0000000..e7deb12
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/master_slave/my.cnf.master
@@ -0,0 +1,127 @@
+#
+# The MySQL database server configuration file.
+#
+# You can copy this to one of:
+# - "/etc/mysql/my.cnf" to set global options,
+# - "~/.my.cnf" to set user-specific options.
+#
+# One can use all long options that the program supports.
+# Run program with --help to get a list of available options and with
+# --print-defaults to see which it would actually understand and use.
+#
+# For explanations see
+# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
+
+# This will be passed to all mysql clients
+# It has been reported that passwords should be enclosed with ticks/quotes
+# escpecially if they contain "#" chars...
+# Remember to edit /etc/mysql/debian.cnf when changing the socket location.
+[client]
+port = 3306
+socket = /var/run/mysqld/mysqld.sock
+
+# Here is entries for some specific programs
+# The following values assume you have at least 32M ram
+
+# This was formally known as [safe_mysqld]. Both versions are currently parsed.
+[mysqld_safe]
+socket = /var/run/mysqld/mysqld.sock
+nice = 0
+
+[mysqld]
+#
+# * Basic Settings
+#
+user = mysql
+pid-file = /var/run/mysqld/mysqld.pid
+socket = /var/run/mysqld/mysqld.sock
+port = 3306
+basedir = /usr
+datadir = /var/lib/mysql
+tmpdir = /tmp
+lc-messages-dir = /usr/share/mysql
+skip-external-locking
+#
+# Instead of skip-networking the default is now to listen only on
+# localhost which is more compatible and is not less secure.
+# bind-address = 127.0.0.1
+#
+# * Fine Tuning
+#
+key_buffer = 16M
+max_allowed_packet = 16M
+thread_stack = 192K
+thread_cache_size = 8
+# This replaces the startup script and checks MyISAM tables if needed
+# the first time they are touched
+myisam-recover = BACKUP
+max_connections = 3000
+#table_cache = 64
+#thread_concurrency = 10
+#
+# * Query Cache Configuration
+#
+query_cache_limit = 1M
+query_cache_size = 16M
+#
+# * Logging and Replication
+#
+# Both location gets rotated by the cronjob.
+# Be aware that this log type is a performance killer.
+# As of 5.1 you can enable the log at runtime!
+#general_log_file = /var/log/mysql/mysql.log
+#general_log = 1
+#
+# Error log - should be very few entries.
+#
+log_error = /var/log/mysql/error.log
+#
+# Here you can see queries with especially long duration
+#log_slow_queries = /var/log/mysql/mysql-slow.log
+#long_query_time = 2
+#log-queries-not-using-indexes
+#
+# The following can be used as easy to replay backup logs or for replication.
+# note: if you are setting up a replication slave, see README.Debian about
+# other settings you may need to change.
+server-id = 1
+log_bin = /var/log/mysql/mysql-bin.log
+expire_logs_days = 10
+max_binlog_size = 100M
+binlog_do_db = tpcw
+#binlog_ignore_db = include_database_name
+#
+# * InnoDB
+#
+# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
+# Read the manual for more InnoDB related options. There are many!
+#
+# * Security Features
+#
+# Read the manual, too, if you want chroot!
+# chroot = /var/lib/mysql/
+#
+# For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
+#
+# ssl-ca=/etc/mysql/cacert.pem
+# ssl-cert=/etc/mysql/server-cert.pem
+# ssl-key=/etc/mysql/server-key.pem
+
+
+
+[mysqldump]
+quick
+quote-names
+max_allowed_packet = 16M
+
+[mysql]
+#no-auto-rehash # faster start of mysql but no tab completition
+
+[isamchk]
+key_buffer = 16M
+
+#
+# * IMPORTANT: Additional settings that can override those from this file!
+# The files must end with '.cnf', otherwise they'll be ignored.
+#
+!includedir /etc/mysql/conf.d/
diff --git a/cloudscale/deployment_scripts/scripts/software/master_slave/my.cnf.slave b/cloudscale/deployment_scripts/scripts/software/master_slave/my.cnf.slave
new file mode 100644
index 0000000..b8cd9ce
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/master_slave/my.cnf.slave
@@ -0,0 +1,128 @@
+#
+# The MySQL database server configuration file.
+#
+# You can copy this to one of:
+# - "/etc/mysql/my.cnf" to set global options,
+# - "~/.my.cnf" to set user-specific options.
+#
+# One can use all long options that the program supports.
+# Run program with --help to get a list of available options and with
+# --print-defaults to see which it would actually understand and use.
+#
+# For explanations see
+# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
+
+# This will be passed to all mysql clients
+# It has been reported that passwords should be enclosed with ticks/quotes
+# escpecially if they contain "#" chars...
+# Remember to edit /etc/mysql/debian.cnf when changing the socket location.
+[client]
+port = 3306
+socket = /var/run/mysqld/mysqld.sock
+
+# Here is entries for some specific programs
+# The following values assume you have at least 32M ram
+
+# This was formally known as [safe_mysqld]. Both versions are currently parsed.
+[mysqld_safe]
+socket = /var/run/mysqld/mysqld.sock
+nice = 0
+
+[mysqld]
+#
+# * Basic Settings
+#
+user = mysql
+pid-file = /var/run/mysqld/mysqld.pid
+socket = /var/run/mysqld/mysqld.sock
+port = 3306
+basedir = /usr
+datadir = /var/lib/mysql
+tmpdir = /tmp
+lc-messages-dir = /usr/share/mysql
+skip-external-locking
+#
+# Instead of skip-networking the default is now to listen only on
+# localhost which is more compatible and is not less secure.
+#bind-address = 127.0.0.1
+#
+# * Fine Tuning
+#
+key_buffer = 16M
+max_allowed_packet = 16M
+thread_stack = 192K
+thread_cache_size = 8
+# This replaces the startup script and checks MyISAM tables if needed
+# the first time they are touched
+myisam-recover = BACKUP
+max_connections = 3000
+#table_cache = 64
+#thread_concurrency = 10
+#
+# * Query Cache Configuration
+#
+query_cache_limit = 1M
+query_cache_size = 16M
+#
+# * Logging and Replication
+#
+# Both location gets rotated by the cronjob.
+# Be aware that this log type is a performance killer.
+# As of 5.1 you can enable the log at runtime!
+#general_log_file = /var/log/mysql/mysql.log
+#general_log = 1
+#
+# Error log - should be very few entries.
+#
+log_error = /var/log/mysql/error.log
+#
+# Here you can see queries with especially long duration
+#log_slow_queries = /var/log/mysql/mysql-slow.log
+#long_query_time = 2
+#log-queries-not-using-indexes
+#
+# The following can be used as easy to replay backup logs or for replication.
+# note: if you are setting up a replication slave, see README.Debian about
+# other settings you may need to change.
+#server-id = 1
+relay-log = /var/log/mysql/mysql-relay-bin.log
+log_bin = /var/log/mysql/mysql-bin.log
+expire_logs_days = 10
+max_binlog_size = 100M
+binlog_do_db = tpcw
+#binlog_ignore_db = include_database_name
+#
+# * InnoDB
+#
+# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
+# Read the manual for more InnoDB related options. There are many!
+#
+# * Security Features
+#
+# Read the manual, too, if you want chroot!
+# chroot = /var/lib/mysql/
+#
+# For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
+#
+# ssl-ca=/etc/mysql/cacert.pem
+# ssl-cert=/etc/mysql/server-cert.pem
+# ssl-key=/etc/mysql/server-key.pem
+
+
+
+[mysqldump]
+quick
+quote-names
+max_allowed_packet = 16M
+
+[mysql]
+#no-auto-rehash # faster start of mysql but no tab completition
+
+[isamchk]
+key_buffer = 16M
+
+#
+# * IMPORTANT: Additional settings that can override those from this file!
+# The files must end with '.cnf', otherwise they'll be ignored.
+#
+!includedir /etc/mysql/conf.d/
diff --git a/cloudscale/deployment_scripts/scripts/software/master_slave/setup_master.sh b/cloudscale/deployment_scripts/scripts/software/master_slave/setup_master.sh
new file mode 100644
index 0000000..28a13c2
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/master_slave/setup_master.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+sudo service mysql restart
+mysql -u root -ppassword -e "GRANT REPLICATION SLAVE ON *.* TO 'slave_user'@'%' IDENTIFIED BY 'password';"
+mysql -u root -ppassword -e "FLUSH PRIVILEGES;"
+mysql -u root -ppassword -e "CREATE DATABASE IF NOT EXISTS tpcw; USE tpcw;"
+master_file=$(mysql -u root -ppassword -s -N -e 'SHOW MASTER STATUS;' | awk '{ print $1 }')
+master_position=$(mysql -u root -ppassword -s -N -e 'SHOW MASTER STATUS;' | awk '{ print $2 }')
+echo "$master_file|$master_position"
\ No newline at end of file
diff --git a/cloudscale/deployment_scripts/scripts/software/my.cnf b/cloudscale/deployment_scripts/scripts/software/my.cnf
new file mode 100644
index 0000000..273dbdc
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/my.cnf
@@ -0,0 +1,88 @@
+[client]
+port = 3306
+socket = /var/run/mysqld/mysqld.sock
+
+[mysqld_safe]
+socket = /var/run/mysqld/mysqld.sock
+nice = 0
+
+[mysqld]
+#
+# * Basic Settings
+#
+user = mysql
+pid-file = /var/run/mysqld/mysqld.pid
+socket = /var/run/mysqld/mysqld.sock
+port = 3306
+basedir = /usr
+datadir = /var/lib/mysql
+tmpdir = /tmp
+lc-messages-dir = /usr/share/mysql
+skip-external-locking
+
+#bind-address = 0.0.0.0
+#
+# * Fine Tuning
+#
+key_buffer = 16M
+max_allowed_packet = 16M
+thread_stack = 192K
+thread_cache_size = 8
+# This replaces the startup script and checks MyISAM tables if needed
+# the first time they are touched
+myisam-recover = BACKUP
+#max_connections = 100
+#table_cache = 64
+#thread_concurrency = 10
+#
+# * Query Cache Configuration
+#
+query_cache_limit = 1M
+query_cache_size = 16M
+
+log_error = /var/log/mysql/error.log
+
+#
+# * Galera settings
+#
+# Mandatory Settings
+binlog_format=ROW
+default_storage_engine=InnoDB
+innodb_autoinc_lock_mode=2
+
+# Optional mysqld Settings
+innodb_buffer_pool_size=28G
+innodb_log_file_size=100M
+innodb_file_per_table=1
+innodb_flush_log_at_trx_commit=0
+innodb_locks_unsafe_for_binlog=1 #disables gap locking
+
+# Basic wsrep Provider Settings
+wsrep_provider=/usr/lib/galera/libgalera_smm.so
+wsrep_provider_options="gcache.szie=32G;gcache.page_size=1G;"
+wsrep_cluster_name='galera_cluster'
+
+
+# Optional Memory Settings
+gcs.recv_q_hard_limit=4G
+gcs.recv_q_soft_limit=2G
+gcs.max_throttle=0.25T
+
+[mysqldump]
+quick
+quote-names
+max_allowed_packet = 16M
+
+[mysql]
+#no-auto-rehash # faster start of mysql but no tab completition
+
+[isamchk]
+key_buffer = 16M
+
+#
+# * IMPORTANT: Additional settings that can override those from this file!
+# The files must end with '.cnf', otherwise they'll be ignored.
+#
+!includedir /etc/mysql/conf.d/
+
+
diff --git a/cloudscale/deployment_scripts/scripts/software/start-mysql-galera-first-node.sh b/cloudscale/deployment_scripts/scripts/software/start-mysql-galera-first-node.sh
new file mode 100644
index 0000000..98858ae
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/start-mysql-galera-first-node.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+echo "NOTE: starting mysql service"
+service mysql start --wsrep-new-cluster --wsrep_cluster_address="gcomm://"
+
+# wait for mysql to start
+RETRIES=100
+COUNTER=0
+false
+while [ $? -ne 0 ]
+do
+ let COUNTER=COUNTER+1
+ if [ $COUNTER -gt $RETRIES ]
+ then
+ echo "ERROR: Could not connect to mysql server in $RETRIES tries!"
+ exit 1
+ fi
+ sleep 3
+ echo "NOTE: $COUNTER. try to connect to mysql server."
+ mysqladmin ping --host=127.0.0.1 > /dev/null 2>&1
+done
+echo "NOTE: Connected to mysql server"
+
+
+echo "NOTE: finished"
diff --git a/cloudscale/deployment_scripts/scripts/software/start-mysql-galera-other-nodes.sh b/cloudscale/deployment_scripts/scripts/software/start-mysql-galera-other-nodes.sh
new file mode 100644
index 0000000..3f0ba00
--- /dev/null
+++ b/cloudscale/deployment_scripts/scripts/software/start-mysql-galera-other-nodes.sh
@@ -0,0 +1,50 @@
+
+echo "NOTE: wait for first node to start"
+RETRIES=400
+COUNTER=0
+false
+while [ $? -ne 0 ]
+do
+ let COUNTER=COUNTER+1
+ if [ $COUNTER -gt $RETRIES ]
+ then
+ echo "ERROR: Could not connect to first node in $RETRIES tries!"
+ exit 1
+ fi
+ sleep 3
+ echo "NOTE: $COUNTER. try to connect to first node."
+ mysqladmin ping --host=$FIRST_NODE_IP > /dev/null 2>&1
+done
+echo "NOTE: Connected to first node"
+
+
+
+echo "NOTE: starting mysql service"
+service mysql start --wsrep_cluster_address="gcomm://$FIRST_NODE_IP"
+
+echo "NOTE: wait for mysql to start"
+RETRIES=400
+COUNTER=0
+false
+
+while [ $? -ne 0 ]
+do
+ let COUNTER=COUNTER+1
+ if [ $COUNTER -gt $RETRIES ]
+ then
+ echo "ERROR: Could not connect to mysql server in $RETRIES tries!"
+ exit 1
+ fi
+ sleep 3
+ if [ $(( $COUNTER % 40 )) -eq 0 ]
+ then
+ echo "NOTE: starting mysql service again"
+ service mysql start --wsrep_cluster_address="gcomm://$FIRST_NODE_IP"
+ fi
+ echo "NOTE: $COUNTER. try to connect to mysql server."
+ mysqladmin ping --host=127.0.0.1 > /dev/null 2>&1
+done
+echo "NOTE: Connected to mysql server"
+
+
+echo "NOTE: finished"
diff --git a/dist/cloudscale-deployment-scripts-0.1.0.tar.gz b/dist/cloudscale-deployment-scripts-0.1.0.tar.gz
new file mode 100644
index 0000000..b4bd964
Binary files /dev/null and b/dist/cloudscale-deployment-scripts-0.1.0.tar.gz differ
LICENSE.txt 0(+0 -0)
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/LICENSE.txt
MANIFEST.in 1(+1 -0)
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..e29da8a
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1 @@
+recursive-include cloudscale *
README.txt 43(+43 -0)
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..2bc961f
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,43 @@
+==================
+Distributed JMeter
+==================
+
+Distributed JMeter provides such and such and so and so. You might find
+it most useful for tasks involving <x> and also <y>. Typical usage
+often looks like this::
+
+ #!/usr/bin/env python
+
+ from towelstuff import location
+ from towelstuff import utils
+
+ if utils.has_towel():
+ print "Your towel is located:", location.where_is_my_towel()
+
+(Note the double-colon and 4-space indent formatting above.)
+
+Paragraphs are separated by blank lines. *Italics*, **bold**,
+and ``monospace`` look like this.
+
+
+A Section
+=========
+
+Lists look like this:
+
+* First
+
+* Second. Can be multiple lines
+but must be indented properly.
+
+A Sub-Section
+-------------
+
+Numbered lists look like you'd expect:
+
+1. hi there
+
+2. must be going
+
+Urls are http://like.this and links can be
+written `like this <http://www.example.com/foo/bar>`_.
setup.py 19(+19 -0)
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..febe1c9
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,19 @@
+from distutils.core import setup
+from setuptools import find_packages
+
+setup(
+ name='cloudscale-deployment-scripts',
+ version='0.1.0',
+ author='Simon Ivansek',
+ author_email='simon.ivansek@xlab.si',
+ packages=find_packages(),
+ package_data={'' : ['*.cfg', '*.sh', '*.conf']},
+ license='LICENSE.txt',
+ description='Deployment scripts for CloudScale project',
+ long_description=open('README.txt').read(),
+ include_package_data=True,
+ install_requires=[
+ "boto==2.36.0",
+ "python-novaclient==2.22.0",
+ ],
+)
\ No newline at end of file