diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..549e00a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,33 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000..e76d1f3
--- /dev/null
+++ b/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * 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
+ *
+ * https://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.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.6";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..2cc7d4a
Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..642d572
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..4f1f5af
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,4 @@
+FROM openjdk:8-jdk-alpine
+ARG JAR_FILE=target/*.jar
+COPY ${JAR_FILE} app.jar
+ENTRYPOINT ["java","-jar","/app.jar"]
\ No newline at end of file
diff --git a/cloud_sql_proxy b/cloud_sql_proxy
new file mode 100755
index 0000000..4195a61
Binary files /dev/null and b/cloud_sql_proxy differ
diff --git a/mvnw b/mvnw
new file mode 100755
index 0000000..a16b543
--- /dev/null
+++ b/mvnw
@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# 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
+#
+# https://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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/mvnw.cmd b/mvnw.cmd
new file mode 100644
index 0000000..c8d4337
--- /dev/null
+++ b/mvnw.cmd
@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Found %WRAPPER_JAR%
+ )
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+ )
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ )
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ if "%MVNW_VERBOSE%" == "true" (
+ echo Finished downloading %WRAPPER_JAR%
+ )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..74541c1
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,136 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.3.4.RELEASE
+
+
+ com.springboot
+ bookmyshow
+ 0.0.1-SNAPSHOT
+ bookmyshow
+ online movie ticket booking
+
+
+ 1.8
+
+
+
+
+ com.google.cloud
+ libraries-bom
+ 4.4.1
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jetty
+
+
+ org.springframework.boot
+ spring-boot-starter-web-services
+
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+ io.springfox
+ springfox-swagger2
+ 2.6.1
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ io.springfox
+ springfox-swagger-ui
+ 2.6.1
+
+
+ org.json
+ json
+ 20190722
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ io.jsonwebtoken
+ jjwt
+ 0.9.1
+
+
+ com.google.cloud
+ google-cloud-datastore
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ com.google.cloud.sql
+ mysql-socket-factory-connector-j-8
+ 1.1.0
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ com.google.cloud.tools
+ appengine-maven-plugin
+ 2.2.0
+
+ dummybms
+ dummybms
+
+
+
+
+
+
diff --git a/src/main/appengine/app.yaml b/src/main/appengine/app.yaml
new file mode 100644
index 0000000..173a00e
--- /dev/null
+++ b/src/main/appengine/app.yaml
@@ -0,0 +1,7 @@
+runtime: java
+env: flex
+readiness_check:
+ app_start_timeout_sec: 800
+handlers:
+- url: /.*
+ script: this field is required, but ignored
\ No newline at end of file
diff --git a/src/main/java/com/dummy/bookmyshow/BookmyshowApplication.java b/src/main/java/com/dummy/bookmyshow/BookmyshowApplication.java
new file mode 100644
index 0000000..089b96f
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/BookmyshowApplication.java
@@ -0,0 +1,65 @@
+package com.dummy.bookmyshow;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Configuration;
+
+import com.dummy.bookmyshow.entity.User;
+import com.dummy.bookmyshow.enums.UserType;
+import com.dummy.bookmyshow.repository.UserRepository;
+
+
+
+@SpringBootApplication
+@Configuration
+public class BookmyshowApplication {
+
+ private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
+
+ @Autowired
+ private UserRepository userRepository;
+
+ public static void main(String[] args) {
+ SpringApplication.run(BookmyshowApplication.class, args);
+ }
+
+ /**
+ * Initialize the admin users
+ */
+ @PostConstruct
+ public void initUsers() {
+ this.LOGGER.info("creating admin and service users.....");
+ User adminUser = new User();
+ adminUser.setUserName("admin");
+ adminUser.setAuthentication("admin");
+ adminUser.setFirstName("admin");
+ adminUser.setLastName("user");
+ adminUser.setEmail("admin@bms.com");
+ adminUser.setMobileNumber("9801234589");
+ adminUser.setUserType(UserType.ADMIN);
+
+ User serviceUser = new User();
+ serviceUser.setUserName("service");
+ serviceUser.setAuthentication("service");
+ serviceUser.setFirstName("service");
+ serviceUser.setLastName("user");
+ serviceUser.setEmail("service@bms.com");
+ serviceUser.setMobileNumber("9801234589");
+ serviceUser.setUserType(UserType.ADMIN);
+
+ List users = new ArrayList<>();
+ users.add(serviceUser);
+ users.add(adminUser);
+ userRepository.saveAll(users);
+ this.LOGGER.info("successfully created admin user with name : admin , password: ****** and service user with name: service and password: ***** ");
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/SwaggerConfig.java b/src/main/java/com/dummy/bookmyshow/SwaggerConfig.java
new file mode 100644
index 0000000..3e979b4
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/SwaggerConfig.java
@@ -0,0 +1,22 @@
+package com.dummy.bookmyshow;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+@Configuration
+@EnableSwagger2
+public class SwaggerConfig {
+ @Bean
+ public Docket api() {
+ return new Docket(DocumentationType.SWAGGER_2)
+ .select()
+ .apis(RequestHandlerSelectors.any())
+ .paths(PathSelectors.any())
+ .build();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/dummy/bookmyshow/controller/CastController.java b/src/main/java/com/dummy/bookmyshow/controller/CastController.java
new file mode 100644
index 0000000..e2f5a6b
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/controller/CastController.java
@@ -0,0 +1,139 @@
+package com.dummy.bookmyshow.controller;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Optional;
+
+import org.json.JSONArray;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.dummy.bookmyshow.entity.Cast;
+import com.dummy.bookmyshow.entity.Movie;
+import com.dummy.bookmyshow.repository.CastRepository;
+import com.dummy.bookmyshow.repository.MovieRepository;
+import com.dummy.bookmyshow.service.impl.CastServiceImpl;
+import com.dummy.bookmyshow.util.ResponseParser;
+
+@RestController
+@RequestMapping(value = "/v1")
+@Component
+@Configuration
+public class CastController {
+
+ private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
+ @Autowired
+ private ResponseParser responseParser;
+
+ @Autowired
+ private CastRepository castRepo;
+
+ @Autowired
+ private MovieRepository movieRepo;
+
+ @Autowired
+ private CastServiceImpl castService;
+
+ /**
+ * The end point will add the cast for the movie , there is one to many mapping
+ * between movie to cast, i.e one movie can have multiple casts TODO : Only
+ * ADMIN user is allowed to use this API
+ *
+ * @param cast
+ * @return the Response entity
+ */
+ @RequestMapping(value = "/addCast", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
+ public ResponseEntity addCast(@RequestBody List casts) {
+ try {
+ this.LOGGER.info("addCast() called with " + casts.size() + " casts");
+ for (Cast cast : casts) {
+ validateInput(cast);
+ this.LOGGER.info("addCast() saving cast for movie id as " + cast.getMovieId());
+ this.castRepo.save(cast);
+ // update movie table with this movie id and this cast id
+ Optional existingMovie = this.movieRepo.findById(cast.getMovieId());
+ Movie movie = existingMovie.get();
+ if (movie != null) {
+ this.LOGGER.info("addCast() trying to update cast id in movie ");
+ movie.setCastId(cast.getMovieId());
+ movie.setUpdatedOn(LocalDateTime.now());
+ this.movieRepo.save(movie);
+ this.LOGGER.info("addCast() successfully updated cast id " + cast.getMovieId() + " in movie: "
+ + movie.getName());
+ }
+ this.LOGGER.info("addCast() saved cast for movie id " + cast.getMovieId() + " in DB");
+ }
+
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.CREATED.value(),
+ "Successfully saved cast for movies ", "Successfully saved cast for movies "), HttpStatus.CREATED);
+
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error("Error creating cast " + e.getMessage());
+ return new ResponseEntity<>(
+ this.responseParser.build(HttpStatus.BAD_REQUEST.value(), e.getMessage(), e.getMessage()),
+ HttpStatus.BAD_REQUEST);
+
+ } catch (Exception ex) {
+ this.LOGGER.error("Error creating cast object " + ex.getMessage());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ ex.getMessage(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ }
+
+ /**
+ * This end point will retrieve the cast details for a movie
+ *
+ * @param movieId
+ * @return the ResponseEntity
+ */
+ @RequestMapping(value = "/getCast", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
+ public ResponseEntity addCast(@RequestParam("movieId") String movieId) {
+ try {
+ this.LOGGER.info("getCast() called with input: " + movieId);
+ JSONArray casts = this.castService.findByMovieId(movieId);
+ this.LOGGER.info("getCast() successfully fetched cast " + casts.toString());
+ return new ResponseEntity<>(casts.toString(), HttpStatus.CREATED);
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error("Error getCast " + e.getMessage());
+ return new ResponseEntity<>(
+ this.responseParser.build(HttpStatus.BAD_REQUEST.value(), e.getMessage(), e.getMessage()),
+ HttpStatus.BAD_REQUEST);
+ } catch (Exception ex) {
+ this.LOGGER.error("Error creating cast object " + ex.getMessage());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ ex.getMessage(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * This method will validate the input for cast object
+ *
+ * @param cast
+ */
+ private void validateInput(Cast cast) {
+ try {
+ Assert.notNull(cast, "User object must not be null");
+ Assert.hasLength(cast.getCastDetails(), "cast details must not be null or empty");
+ Assert.hasLength(cast.getCharacterName(), "Cast character must not be null or empty");
+ Assert.hasLength(cast.getCharacterOccupation(), "Cast character occupation must not be null or empty");
+ Assert.hasLength(cast.getMovieId(), "Movie duration must not be null or empty");
+ Optional existingTheater = this.movieRepo.findById(cast.getMovieId());
+ Assert.isTrue(existingTheater.get() != null, "Invalid movie id passed, no movie found with this id ");
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error(e.getMessage());
+ throw new IllegalArgumentException(e.getMessage());
+ }
+ }
+}
diff --git a/src/main/java/com/dummy/bookmyshow/controller/GenericController.java b/src/main/java/com/dummy/bookmyshow/controller/GenericController.java
new file mode 100644
index 0000000..ed051ba
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/controller/GenericController.java
@@ -0,0 +1,180 @@
+package com.dummy.bookmyshow.controller;
+
+import java.util.List;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.dummy.bookmyshow.entity.SeatMatrix;
+import com.dummy.bookmyshow.service.impl.GenericServiceImpl;
+import com.dummy.bookmyshow.util.ResponseParser;
+
+@RestController
+@RequestMapping(value = "/v1")
+@Component
+@Configuration
+public class GenericController {
+
+ private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
+
+ @Autowired
+ private ResponseParser responseParser;
+
+ @Autowired
+ private GenericServiceImpl genericService;
+
+ /**
+ * The end point will get the list of supported cities by the application
+ *
+ * @return the ResponseEntity
+ */
+ @RequestMapping(value = "/getSupportedCities", method = RequestMethod.GET, produces = "application/json")
+ public ResponseEntity getSupportedCities() {
+ try {
+ this.LOGGER.info("getSupportedCities() called ");
+ List supportedCities = this.genericService.getSupportedCities();
+ JSONArray result = new JSONArray();
+
+ for (String city : supportedCities) {
+ JSONObject obj = new JSONObject();
+ obj.put("name", city);
+ result.put(obj);
+ }
+ this.LOGGER.info("getSupportedCities() supported cities: " + result.toString());
+ return new ResponseEntity<>(result.toString(), HttpStatus.OK);
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error("Error in getSupportedCities() " + e.getMessage());
+ return new ResponseEntity<>(
+ this.responseParser.build(HttpStatus.BAD_REQUEST.value(), e.getMessage(), e.getMessage()),
+ HttpStatus.BAD_REQUEST);
+ } catch (Exception ex) {
+ this.LOGGER.error("Error in getSupportedCities() " + ex.getMessage());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ ex.getMessage(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ }
+
+ /**
+ * This end point will return the movies now showing in a city
+ *
+ * @param city
+ * @return the response entity
+ */
+ @RequestMapping(value = "/getMoviesByCity", method = RequestMethod.GET, produces = "application/json")
+ public ResponseEntity getMoviesByCity(@RequestParam("City") String city) {
+ try {
+ this.LOGGER.info("getMoviesByCity() called with city name: " + city);
+ JSONArray availableMovies = this.genericService.getAvailableMovies(city);
+ this.LOGGER.debug("getMoviesByCity() movies in the city: " + availableMovies.toString());
+ return new ResponseEntity<>(availableMovies.toString(), HttpStatus.OK);
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error("Error in getMoviesByCity() " + e.getMessage());
+ return new ResponseEntity<>(
+ this.responseParser.build(HttpStatus.BAD_REQUEST.value(), e.getMessage(), e.getMessage()),
+ HttpStatus.BAD_REQUEST);
+ } catch (Exception ex) {
+ this.LOGGER.error("Error in getMoviesByCity() " + ex.getMessage());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ ex.getMessage(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * This end point will return screens which are showing the movies in same city
+ *
+ * @return ResponseEntity
+ */
+ @RequestMapping(value = "/getScreensShowingMovie", method = RequestMethod.GET, produces = "application/json")
+ public ResponseEntity getScreensShowingMovie(@RequestParam("theaterId") String theaterId,
+ @RequestParam("movieId") String movieId, @RequestParam("city") String city) {
+ try {
+ this.LOGGER.info("getScreensShowingMovie() called with input: theaterId " + theaterId + " city: " + city
+ + " movieId: " + movieId);
+ JSONObject screensShowingMovie = this.genericService.getScreensShowingMovie(theaterId, movieId, city);
+ this.LOGGER.info("getScreensShowingMovie() screens showing " + movieId + " in : " + city + " are: "
+ + screensShowingMovie.toString());
+ return new ResponseEntity<>(screensShowingMovie.toString(), HttpStatus.OK);
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error("Error in getScreensShowingMovie() " + e.getMessage());
+ return new ResponseEntity<>(
+ this.responseParser.build(HttpStatus.BAD_REQUEST.value(), e.getMessage(), e.getMessage()),
+ HttpStatus.BAD_REQUEST);
+ } catch (Exception ex) {
+ this.LOGGER.error("Error in getScreensShowingMovie() " + ex.getMessage());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ ex.getMessage(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * This end point will gives the details about availability of seats for a movie
+ * , in a city for a user and based on start time
+ *
+ * @param movieId
+ * @param theaterId
+ * @param screenStartsAt
+ * @return
+ */
+ @RequestMapping(value = "/getAvailabilityOnAScreen", method = RequestMethod.GET, produces = "application/json")
+ public ResponseEntity getAvailabilityOnAScreen(@RequestParam("movieId") String movieId,
+ @RequestParam("theaterId") String theaterId, @RequestParam("screenStartsAt") String screenStartsAt) {
+ try {
+ this.LOGGER.info("getAvailabilityOnAScreen() called with input: movieId: " + movieId + " theaterid: "
+ + theaterId + ": screenStartsAt :" + screenStartsAt);
+ JSONArray seatsMatrix = this.genericService.getSeatMatrix(movieId, theaterId, screenStartsAt);
+ return new ResponseEntity<>(seatsMatrix.toString(), HttpStatus.OK);
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error("Error getAvailabilityOnAScreen() " + e.getMessage());
+ return new ResponseEntity<>(
+ this.responseParser.build(HttpStatus.BAD_REQUEST.value(), e.getMessage(), e.getMessage()),
+ HttpStatus.BAD_REQUEST);
+ } catch (Exception ex) {
+ this.LOGGER.error("Error in getAvailabilityOnAScreen()" + ex.getMessage());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ ex.getMessage(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * This end point will book the seats for a movie , in a theater and for a user
+ * The end point will first check if the seat is already booked in same theater
+ * for a movie, if not then book it
+ *
+ * @param seatsToBook
+ * @param userName
+ * @return ResponseEntity
+ */
+ @RequestMapping(value = "/bookSeats", method = RequestMethod.POST, produces = "application/json")
+ public ResponseEntity bookSeats(@RequestBody List seatsToBook,
+ @RequestParam("userName") String userName) {
+ try {
+ this.LOGGER.info("bookSeats() called with input: " + seatsToBook.toString() + " user: " + userName);
+ JSONObject bookingDetails = this.genericService.bookSeats(seatsToBook, userName);
+ this.LOGGER.info("bookSeats() booking details: " + bookingDetails);
+ return new ResponseEntity<>(bookingDetails.toString(), HttpStatus.OK);
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error("Error in bookSeats() " + e.getMessage());
+ return new ResponseEntity<>(
+ this.responseParser.build(HttpStatus.BAD_REQUEST.value(), e.getMessage(), e.getMessage()),
+ HttpStatus.BAD_REQUEST);
+ } catch (Exception ex) {
+ this.LOGGER.error("Error in bookSeats() " + ex.getMessage());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ ex.getMessage(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/controller/MovieController.java b/src/main/java/com/dummy/bookmyshow/controller/MovieController.java
new file mode 100644
index 0000000..d7d33ab
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/controller/MovieController.java
@@ -0,0 +1,99 @@
+package com.dummy.bookmyshow.controller;
+
+import java.time.LocalDateTime;
+import java.util.Optional;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.dummy.bookmyshow.entity.Movie;
+import com.dummy.bookmyshow.entity.Theater;
+import com.dummy.bookmyshow.repository.MovieRepository;
+import com.dummy.bookmyshow.repository.TheaterRepository;
+import com.dummy.bookmyshow.util.ResponseParser;
+
+@RestController
+@RequestMapping(value = "/v1")
+@Component
+@Configuration
+public class MovieController {
+ private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
+ @Autowired
+ private ResponseParser responseParser;
+
+ @Autowired
+ private MovieRepository movieRepo;
+
+ @Autowired
+ private TheaterRepository theaterRepo;
+
+ /**
+ * Register a movie
+ * TODO : Only ADMIN user is allowed to use this API
+ * @param movie
+ * @return
+ */
+ @RequestMapping(value = "/registerMovie", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
+ public ResponseEntity registerMovie(@RequestBody Movie movie) {
+ try {
+ this.LOGGER.info("registerMovie() called with input: " + movie.toString());
+ validateInput(movie);
+ Movie newMovie = movie;
+ String movieId = newMovie.getName().replaceAll("\\s", "");
+ newMovie.setMovieId(movieId);
+ newMovie.setCreatedOn(LocalDateTime.now());
+ this.LOGGER.info("registerMovie() setting movie id as " + movieId);
+ this.movieRepo.save(newMovie);
+ this.LOGGER.info("registerMovie() saved movie with id " + movieId + " in DB");
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.CREATED.value(),
+ "Successfully registered new movie with id: "+movieId, "Successfully registered new movie with id: "+movieId), HttpStatus.CREATED);
+
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error("Error registering movie " + e.getMessage());
+ return new ResponseEntity<>(
+ this.responseParser.build(HttpStatus.BAD_REQUEST.value(), e.getMessage(), e.getMessage()),
+ HttpStatus.BAD_REQUEST);
+
+ } catch (Exception ex) {
+ this.LOGGER.error("Error registering movie object " + ex.getMessage());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ ex.getMessage(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ }
+
+ private void validateInput(Movie movie) {
+ try {
+ Assert.notNull(movie, "User object must not be null");
+ Assert.hasLength(movie.getName(), "movie name must not be null or empty");
+ Assert.hasLength(movie.getPosterUrl(), "Poster url must not be null or empty");
+ Assert.hasLength(movie.getDuration(), "Movie duration must not be null or empty");
+ Assert.hasLength(movie.getReleaseYear(), "Movie duration must not be null or empty");
+ Assert.hasLength(movie.getTrailerUrl(), "Movie trailer url must not be null or empty");
+ Assert.hasLength(movie.getActiveDateEnd().toString(), "Movie activate date end must not be null or empty");
+ Assert.hasLength(movie.getActiveDateStart().toString(),
+ "Movie active date start must not be null or empty");
+ Assert.hasLength(movie.getLanguage().toString(), "Movie language must not be null or empty");
+ Assert.hasLength(movie.getType().toString(), "Movie type must not be null or empty");
+ Assert.notNull(movie.getTheaterId(), "theater id must not be null");
+ Optional existingTheater = this.theaterRepo.findById(movie.getTheaterId());
+ Assert.isTrue(existingTheater.get() != null, "Invalid theater id passed, no theater found with this id ");
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error(e.getMessage());
+ throw new IllegalArgumentException(e.getMessage());
+
+ }
+
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/controller/ScreenController.java b/src/main/java/com/dummy/bookmyshow/controller/ScreenController.java
new file mode 100644
index 0000000..df71412
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/controller/ScreenController.java
@@ -0,0 +1,99 @@
+package com.dummy.bookmyshow.controller;
+
+import java.util.Optional;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.dummy.bookmyshow.entity.Movie;
+import com.dummy.bookmyshow.entity.Screen;
+import com.dummy.bookmyshow.entity.Theater;
+import com.dummy.bookmyshow.repository.MovieRepository;
+import com.dummy.bookmyshow.repository.ScreenRepository;
+import com.dummy.bookmyshow.repository.TheaterRepository;
+import com.dummy.bookmyshow.util.ResponseParser;
+
+@RestController
+@RequestMapping(value = "/v1")
+@Component
+@Configuration
+public class ScreenController {
+
+ private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
+
+
+ @Autowired
+ private ResponseParser responseParser;
+ @Autowired
+ private ScreenRepository screenRepo;
+ @Autowired
+ private TheaterRepository theaterRepo;
+
+ @Autowired
+ private MovieRepository movieRepo;
+
+ /**
+ * register a screen to theater
+ * TODO : Only ADMIN user is allowed to use this API
+ * TODO : validation on booking a screen on the overlapping time with other screen
+ * @param screen
+ * @return
+ */
+ @RequestMapping(value = "/registerScreen", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
+ public ResponseEntity registerScreen(@RequestBody Screen screen) {
+ try {
+ this.LOGGER.info("registerScreen() called with input: " + screen.toString());
+ validateInput(screen);
+ this.screenRepo.save(screen);
+ this.LOGGER.info("registerScreen() successfully saved screen ");
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.CREATED.value(),
+ "Successfully registered new screen", "Successfully registered new movie"), HttpStatus.CREATED);
+
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error("Error registering screen object " + e.getMessage());
+ return new ResponseEntity<>(
+ this.responseParser.build(HttpStatus.BAD_REQUEST.value(), e.getMessage(), e.getMessage()),
+ HttpStatus.BAD_REQUEST);
+
+ } catch (Exception ex) {
+ this.LOGGER.error("Error registering screen object " + ex.getMessage());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ ex.getMessage(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ }
+
+ private void validateInput(Screen screen) {
+ try {
+ Assert.notNull(screen, "screen object must not be null");
+ Assert.hasLength(screen.getEndsAt().toString(), "screen ends at must not be null or empty");
+ Assert.hasLength(screen.getScreenDetails().getMovieId().toString(), "screen must have a movie id");
+ Assert.hasLength(screen.getScreenDetails().getTheaterId().toString(), "screen must have a theater id");
+ Assert.hasLength(screen.getScreenDetails().getStartsAt().toString(), "screen must have a starts at time ");
+
+ Optional existingTheater = this.theaterRepo.findById(screen.getScreenDetails().getTheaterId());
+
+ Assert.isTrue(existingTheater.get() != null, "Invalid theater id passed, no theater found with this id ");
+
+ Optional existingMovie = this.movieRepo.findById(screen.getScreenDetails().getMovieId());
+
+ Assert.isTrue(existingMovie.get() != null, "Invalid movie id passed, no movie found with this id ");
+
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error(e.getMessage());
+ throw new IllegalArgumentException(e.getMessage());
+
+ }
+
+ }
+}
diff --git a/src/main/java/com/dummy/bookmyshow/controller/SeatMatrixController.java b/src/main/java/com/dummy/bookmyshow/controller/SeatMatrixController.java
new file mode 100644
index 0000000..fc27e86
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/controller/SeatMatrixController.java
@@ -0,0 +1,172 @@
+package com.dummy.bookmyshow.controller;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.dummy.bookmyshow.entity.SeatMatrix;
+import com.dummy.bookmyshow.entity.SeatMatrixPk;
+import com.dummy.bookmyshow.enums.SeatType;
+import com.dummy.bookmyshow.repository.SeatMatrixRepository;
+import com.dummy.bookmyshow.util.ResponseParser;
+
+@RestController
+@RequestMapping(value = "/v1")
+@Component
+@Configuration
+public class SeatMatrixController {
+
+ private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
+
+ private final int DEFAULT_SEAT_COUNT = 50;
+ private final int DEFAULT_SEAT_PRICE = 100;
+
+ @Autowired
+ private ResponseParser responseParser;
+
+ @Autowired
+ private SeatMatrixRepository seatMatrixRepo;
+
+ /**
+ * add custom seat matrix TODO : Only ADMIN user is allowed to use this API
+ *
+ * @param seatMatrix
+ * @return
+ */
+ @RequestMapping(value = "/addCustomSeatMatrix", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
+ public ResponseEntity addSeatMatrix(@RequestBody List seatMatrix) {
+ try {
+ this.LOGGER.info("addSeatMatrix() called");
+ validateInput(seatMatrix);
+ this.LOGGER.info("addSeatMatrix() saving cast for movie id as ");
+ this.seatMatrixRepo.saveAll(seatMatrix);
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.CREATED.value(),
+ "Successfully saved seat matrix", "Successfully saved seat matrix"), HttpStatus.CREATED);
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error("Error creating seat matrix " + e.getMessage());
+ return new ResponseEntity<>(
+ this.responseParser.build(HttpStatus.BAD_REQUEST.value(), e.getMessage(), e.getMessage()),
+ HttpStatus.BAD_REQUEST);
+
+ } catch (Exception ex) {
+ this.LOGGER.error("Error creating seat matrix " + ex.getMessage());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ ex.getMessage(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ }
+
+ /**
+ * Add default seat matrix TODO : Only ADMIN user is allowed to use this API
+ *
+ * @param seatMatrix
+ * @return
+ */
+ @RequestMapping(value = "/addDefaultSeatMatrix", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
+ public ResponseEntity addDefaultSeatMatrix(@RequestBody SeatMatrix seatMatrix) {
+ try {
+ this.LOGGER.info("addSeatMatrix() called");
+ List list = new ArrayList<>();
+ list.add(seatMatrix);
+ validateInput(list);
+
+ for (int i = 0; i < DEFAULT_SEAT_COUNT; i++) {
+ SeatMatrix newMatrix = new SeatMatrix();
+ newMatrix.setBooked(false);
+ newMatrix.setCreatedOn(LocalDateTime.now());
+ newMatrix.setPrice(DEFAULT_SEAT_PRICE);
+ newMatrix.setSeatType(SeatType.NORMAL);
+
+ SeatMatrixPk matrixPk = new SeatMatrixPk();
+ matrixPk.setMovieId(seatMatrix.getPrimaryKey().getMovieId());
+ matrixPk.setScreenStartsAt(seatMatrix.getPrimaryKey().getScreenStartsAt());
+ matrixPk.setTheaterId(seatMatrix.getPrimaryKey().getTheaterId());
+ matrixPk.setSeatNumber(makeSeatNumber(i));
+
+ newMatrix.setPrimaryKey(matrixPk);
+ this.seatMatrixRepo.save(newMatrix);
+
+ }
+
+ return new ResponseEntity<>(
+ this.responseParser.build(HttpStatus.CREATED.value(),
+ "Successfully created detault seat matrix of " + DEFAULT_SEAT_COUNT + " seats",
+ "Successfully created detault seat matrix of: " + DEFAULT_SEAT_COUNT + " seats"),
+ HttpStatus.CREATED);
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error("Error creating seat matrix " + e.getMessage());
+ return new ResponseEntity<>(
+ this.responseParser.build(HttpStatus.BAD_REQUEST.value(), e.getMessage(), e.getMessage()),
+ HttpStatus.BAD_REQUEST);
+
+ } catch (Exception ex) {
+ this.LOGGER.error("Error creating seat matrix " + ex.getMessage());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ ex.getMessage(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ }
+
+ /**
+ * Create seat numbers A0-A9 B0-B9 and so on
+ *
+ * @param i
+ * @return
+ */
+ private String makeSeatNumber(int i) {
+ StringBuffer sb = new StringBuffer();
+ Map map = new HashMap<>();
+ for (char c = 'A'; c <= 'Z'; c++) {
+ int key = c - 'A';
+ char value = c;
+ map.put(key, value);
+ }
+ char ch = map.get(i / 10);
+ int index = i % 10;
+ sb.append("" + ch + index);
+ return sb.toString();
+ }
+
+ /**
+ *
+ * @param seatMatrix
+ */
+ private void validateInput(List seatMatrix) {
+ for (SeatMatrix seat : seatMatrix) {
+ try {
+ Assert.notNull(seat, "seatMatrix object must not be null");
+ Assert.hasLength(seat.getPrimaryKey().getMovieId(), "seatMatrix movie id must not be null or empty");
+ Assert.hasLength(seat.getPrimaryKey().getTheaterId(),
+ "seatMatrix theater id must not be null or empty");
+ Assert.hasLength(seat.getPrimaryKey().getScreenStartsAt(),
+ "seatMatrix screen starts at must not be null or empty");
+ Assert.hasLength(String.valueOf(seat.getPrice()), "seatMatrix price must not be null or empty");
+ Assert.hasLength(seat.getPrimaryKey().getSeatNumber(),
+ "seatMatrix seat number must not be null or empty");
+ Assert.hasLength(seat.getSeatType().toString(), "seatMatrix seat number must not be null or empty");
+ } catch (IllegalArgumentException ex) {
+ this.LOGGER.error(ex.getMessage());
+ throw new IllegalArgumentException(ex.getMessage());
+
+ }
+
+ }
+
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/controller/TheaterController.java b/src/main/java/com/dummy/bookmyshow/controller/TheaterController.java
new file mode 100644
index 0000000..5cda79d
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/controller/TheaterController.java
@@ -0,0 +1,95 @@
+package com.dummy.bookmyshow.controller;
+
+import java.time.LocalDateTime;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.dummy.bookmyshow.entity.Theater;
+import com.dummy.bookmyshow.entity.User;
+import com.dummy.bookmyshow.repository.TheaterRepository;
+import com.dummy.bookmyshow.repository.UserRepository;
+import com.dummy.bookmyshow.util.ResponseParser;
+
+@RestController
+@RequestMapping(value = "/v1")
+@Component
+@Configuration
+public class TheaterController {
+
+ private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
+ @Autowired
+ private TheaterRepository theaterRepo;
+ @Autowired
+ private ResponseParser responseParser;
+ @Autowired
+ private UserRepository userRepo;
+
+ /**
+ * register a theater
+ * @param theater
+ * @return
+ */
+ @RequestMapping(value = "/registerTheater", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
+ public ResponseEntity registerMovie(@RequestBody Theater theater) {
+ try {
+ this.LOGGER.info("registerTheater() called with input: " + theater.toString());
+ validateInput(theater);
+ Theater newTheater = theater;
+ String theaterId = newTheater.getName().replaceAll("\\s", "");
+ newTheater.setTheaterId(theaterId);
+ newTheater.setCreatedOn(LocalDateTime.now());
+ this.LOGGER.info("registerTheater() stting theater id as " + theaterId);
+ this.theaterRepo.save(newTheater);
+ this.LOGGER.info("registerTheater() successfully saved theater with id: " + theaterId);
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.CREATED.value(),
+ "Successfully registered new theater with thaterId: " + theaterId,
+ "Successfully registered new theater with theaterId: " + theaterId), HttpStatus.CREATED);
+
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error("Error registering theater object " + e.getMessage());
+ return new ResponseEntity<>(
+ this.responseParser.build(HttpStatus.BAD_REQUEST.value(), e.getMessage(), e.getMessage()),
+ HttpStatus.BAD_REQUEST);
+
+ } catch (Exception ex) {
+ this.LOGGER.error("Error registering theater object " + ex.getMessage());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ ex.getMessage(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ }
+
+
+ private void validateInput(Theater theater) {
+ try {
+ Assert.notNull(theater, "User object must not be null");
+ Assert.hasLength(theater.getName(), "theater name must not be null or empty");
+ Assert.hasLength(theater.getAddress(), "theater address must not be null or empty");
+ Assert.hasLength(theater.getCity(), "theater city must not be null or empty");
+ Assert.hasLength(theater.getCountry(), "theater country must not be null or empty");
+ Assert.hasLength(theater.getLanguages(), "theater language must not be null or empty");
+ Assert.hasLength(theater.getUserName(), "theater user name must not be null or empty");
+ User existingUser = this.userRepo.findUserByUserName(theater.getUserName());
+ Assert.isTrue(existingUser != null,
+ "Invalid user name passed, no user found with id: " + theater.getUserName());
+ Assert.isTrue((existingUser.getUserType().toString().equals("ADMIN")) , "User is not allowed to add the theater, Only admin user can add a theater");
+
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error(e.getMessage());
+ throw new IllegalArgumentException(e.getMessage());
+
+ }
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/controller/UrlController.java b/src/main/java/com/dummy/bookmyshow/controller/UrlController.java
new file mode 100644
index 0000000..cc2dc15
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/controller/UrlController.java
@@ -0,0 +1,79 @@
+package com.dummy.bookmyshow.controller;
+
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.dummy.bookmyshow.entity.Url;
+import com.dummy.bookmyshow.service.impl.UrlServiceImpl;
+import com.dummy.bookmyshow.util.ResponseParser;
+
+@RestController
+@RequestMapping(value = "/v1")
+@Component
+@Configuration
+public class UrlController {
+
+ private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
+
+
+ @Autowired
+ private ResponseParser responseParser;
+
+ @Autowired
+ private UrlServiceImpl service;
+
+ /**
+ * convert from long to short url
+ * @param url
+ * @return
+ */
+ @RequestMapping(value = "/longToShort", method = RequestMethod.POST, produces = "application/json", consumes = "application/json")
+ public ResponseEntity convertLongUrlToShort(@RequestBody Url url) {
+ try {
+ String shortUrl = this.service.convertToShortUrl(url);
+ JSONObject obj = new JSONObject();
+ obj.put("longUrl", url.getOriginalUrl());
+ obj.put("shortUrl", "https://"+shortUrl);
+ return new ResponseEntity<>(obj.toString(), HttpStatus.OK);
+ } catch (Exception ex) {
+ this.LOGGER.error("Error registering theater object " + ex.getMessage());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ ex.getMessage(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ }
+ /**
+ * convert from short to long
+ * @param shortUrl
+ * @return
+ */
+ @RequestMapping(value = "/shortToLong", method = RequestMethod.GET, produces = "application/json")
+ public ResponseEntity convertshortToLong(@RequestParam("shortUrl")String shortUrl)
+ {
+
+ try {
+ shortUrl = shortUrl.substring(8,shortUrl.length());//remove the https:// part
+ String originalUrl = this.service.getOriginalUrl(shortUrl);
+ JSONObject obj = new JSONObject();
+ obj.put("longUrl", originalUrl);
+ obj.put("shortUrl", shortUrl);
+ return new ResponseEntity<>(obj.toString(), HttpStatus.OK);
+ } catch (Exception ex) {
+ this.LOGGER.error("Error in shortToLong " + ex.getMessage());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ ex.getMessage(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ }
+}
diff --git a/src/main/java/com/dummy/bookmyshow/controller/UserController.java b/src/main/java/com/dummy/bookmyshow/controller/UserController.java
new file mode 100644
index 0000000..bc0813f
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/controller/UserController.java
@@ -0,0 +1,191 @@
+package com.dummy.bookmyshow.controller;
+
+import java.time.LocalDateTime;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.dummy.bookmyshow.entity.User;
+import com.dummy.bookmyshow.enums.UserType;
+import com.dummy.bookmyshow.repository.UserRepository;
+import com.dummy.bookmyshow.security.AuthRequest;
+import com.dummy.bookmyshow.security.JwtUtils;
+import com.dummy.bookmyshow.util.ResponseParser;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@RestController
+@RequestMapping(value = "/v1")
+@Component
+@Configuration
+public class UserController {
+ private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
+
+ private static final Pattern VALID_EMAIL_ADDRESS_REGEX = Pattern
+ .compile("^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,6}$", Pattern.CASE_INSENSITIVE);
+
+ @Autowired
+ private ResponseParser responseParser;
+
+ @Autowired
+ private JwtUtils jwtUtils;
+
+ @Autowired
+ private UserRepository userReposiitory;
+
+ @Autowired
+ private AuthenticationManager authenticationManager;
+
+ /**
+ * get the user details
+ * @param userName
+ * @return
+ */
+ @RequestMapping(value = "/getUserDetails", method = RequestMethod.GET, produces = "application/json")
+ public ResponseEntity getUserDetails(@RequestParam("userName") String userName) {
+ this.LOGGER.info(" getUser () with input params: " + userName);
+ try {
+ User user = this.userReposiitory.findUserByUserName(userName);
+ this.LOGGER.info(" getUser () found the user with input username " + user.toString());
+
+ ObjectMapper mapper = new ObjectMapper();
+ String jsonUser = mapper.writeValueAsString(user);
+ this.LOGGER.info(" getUser () status success! ");
+ return new ResponseEntity<>(jsonUser, HttpStatus.OK);
+
+ } catch (Exception ex) {
+ this.LOGGER.info(" getUser () Error occured: " + ex.getMessage());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(),
+ ex.getMessage(), ex.getMessage()), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ }
+
+ /**
+ * SignUp of a user
+ * This API should not be authenticated
+ * @param user
+ * @return
+ */
+ @RequestMapping(value = "/addUser", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
+ public ResponseEntity addUser(@RequestBody User user) {
+ try {
+ this.LOGGER.info("addUser() called with input: " + user.toString());
+ User newUser = user;
+ validateInput(newUser);
+ String userName = getUserName(user).replaceAll("\\s", "");
+ newUser.setUserName(userName);
+ newUser.setCreatedOn(LocalDateTime.now());
+ this.LOGGER.info("addUser() setting username as " + newUser.getUserName());
+ this.userReposiitory.save(newUser);
+ this.LOGGER.info("successfully saved user object " + newUser.toString());
+ return new ResponseEntity<>(this.responseParser.build(HttpStatus.CREATED.value(), "Successfully saved user with user name: "+newUser.getUserName(),
+ "Successfully saved user with user name: "+newUser.getUserName()), HttpStatus.CREATED);
+ } catch (IllegalArgumentException ex) {
+ this.LOGGER.error("Error Saving user object " + ex.getMessage());
+ return new ResponseEntity<>(
+ this.responseParser.build(HttpStatus.BAD_REQUEST.value(), ex.getMessage(), ex.getMessage()),
+ HttpStatus.BAD_REQUEST);
+ } catch (Exception e) {
+ this.LOGGER.error("Error Saving user object " + e.getMessage());
+ e.printStackTrace();
+ return new ResponseEntity<>(
+ this.responseParser.build(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage(), e.getMessage()),
+ HttpStatus.INTERNAL_SERVER_ERROR);
+
+ }
+
+ }
+
+ /**
+ *
+ * @param authRequest
+ * @return
+ */
+ @RequestMapping(value = "/token", method = RequestMethod.POST, produces = "application/json")
+ public ResponseEntity getToken(@RequestBody AuthRequest authRequest) {
+ JSONObject result = new JSONObject();
+ try {
+ this.LOGGER.info(
+ "getToken() called with username as : " + authRequest.getUsername() + " and password as : *****");
+ authenticationManager.authenticate(
+ new UsernamePasswordAuthenticationToken(authRequest.getUsername(), authRequest.getPassword()));
+ String token = jwtUtils.generateToken(authRequest.getUsername());
+ this.LOGGER.info("getToken() successfully got the jwt token " + token);
+ result.put("token", token);
+ result.put("status", "success");
+ this.LOGGER.info("getToken() returning token with status 200 ");
+ return new ResponseEntity<>(result.toString(), HttpStatus.OK);
+ } catch (Exception e) {
+ this.LOGGER.info("getToken() Error creating jwt token : " + e.getMessage());
+ result.put("message", e.getMessage() + " cause: " + e.getCause());
+ result.put("status", "failed");
+ e.printStackTrace();
+ return new ResponseEntity<>(result.toString(), HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ }
+
+ /**
+ *
+ * @param user
+ */
+ private void validateInput(User user) {
+ try {
+ Assert.notNull(user, "User object must not be null");
+ Assert.hasLength(user.getFirstName(), "User first name must not be null or empty");
+ Assert.hasLength(user.getLastName(), "User last name must not be null or empty");
+ Assert.hasLength(user.getMobileNumber(), "User mobile number must not be empty");
+ Assert.hasLength(user.getUserType().toString(), "User type must not be null or empty");
+ Assert.hasLength(user.getEmail(), "Email must not be null or empty");
+ Assert.hasLength(user.getAuthentication(), "password must not be null or empty");
+ Assert.isTrue(user.getMobileNumber().length() == 10, "Invalid mobile number");
+ switch (user.getUserType().toString().toUpperCase()) {
+ case "ADMIN":
+ user.setUserType(UserType.ADMIN);
+ this.LOGGER.debug("validateInput(user), User type found as ADMIN");
+ break;
+ case "NORMAL":
+ user.setUserType(UserType.NORMAL);
+ this.LOGGER.debug("validateInput(user), User type found as NORMAL");
+ break;
+ default:
+ Assert.isTrue(false, "Only values allowd for user type is : Admin or Normal");
+ }
+ Matcher matcher = VALID_EMAIL_ADDRESS_REGEX.matcher(user.getEmail());
+ Assert.isTrue(matcher.find(), "Invalid email id");
+ Pattern p = Pattern.compile("(0/91)?[7-9][0-9]{9}");
+ Matcher m = p.matcher(user.getMobileNumber());
+ Assert.isTrue((m.find() && m.group().equals(user.getMobileNumber())), "Invalid mobile number");
+ } catch (IllegalArgumentException e) {
+ this.LOGGER.error("input error ", e.getMessage());
+ throw new IllegalArgumentException(e.getMessage());
+ }
+
+ }
+
+ /**
+ * @param user
+ * @return
+ */
+ private String getUserName(User user) {
+ return (user.getLastName() + user.getFirstName() + user.getMobileNumber());
+
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/entity/Booking.java b/src/main/java/com/dummy/bookmyshow/entity/Booking.java
new file mode 100644
index 0000000..48f9fdf
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/entity/Booking.java
@@ -0,0 +1,173 @@
+package com.dummy.bookmyshow.entity;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.format.annotation.DateTimeFormat.ISO;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+@Entity
+@Table(name = "booking")
+public class Booking implements Serializable {
+ private static final long serialVersionUID = 1L;
+ @Id
+ @Column(name = "booking_id", updatable = false, nullable = false)
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long bookingId;
+
+ @Column(name = "user_name")
+ private String userId;
+
+ @Column(name = "theater_id")
+ private String theaterId;
+
+ @Column(name = "payment_id")
+ private UUID paymentId;
+
+ @Column(name = "movie_id")
+ private String movieId;
+
+ @Column(name = "notification_id")
+ private UUID notificationId;
+
+ @Column(name = "total_price")
+ private int totalPrice;
+
+
+ @Column(name = "created_on")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createdOn = LocalDateTime.now();
+
+ @Column(name = "updated_on")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updatedOn;
+
+ @Column(name = "deleted")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime deleted;
+
+ @Column(name = "seat_booked")
+ private int seatBooked;
+
+ @Column(name = "seat_numbers")
+ private String seatNumbers;
+
+ public Long getBookingId() {
+ return bookingId;
+ }
+
+ public void setBookingId(Long bookingId) {
+ this.bookingId = bookingId;
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public String getTheaterId() {
+ return theaterId;
+ }
+
+ public void setTheaterId(String theaterId) {
+ this.theaterId = theaterId;
+ }
+
+ public UUID getPaymentId() {
+ return paymentId;
+ }
+
+ public void setPaymentId(UUID paymentId) {
+ this.paymentId = paymentId;
+ }
+
+ public String getMovieId() {
+ return movieId;
+ }
+
+ public void setMovieId(String movieId) {
+ this.movieId = movieId;
+ }
+
+ public UUID getNotificationId() {
+ return notificationId;
+ }
+
+ public void setNotificationId(UUID notificationId) {
+ this.notificationId = notificationId;
+ }
+
+ public int getTotalPrice() {
+ return totalPrice;
+ }
+
+ public void setTotalPrice(int totalPrice) {
+ this.totalPrice = totalPrice;
+ }
+
+ public LocalDateTime getCreatedOn() {
+ return createdOn;
+ }
+
+ public void setCreatedOn(LocalDateTime createdOn) {
+ this.createdOn = createdOn;
+ }
+
+ public LocalDateTime getUpdatedOn() {
+ return updatedOn;
+ }
+
+ public void setUpdatedOn(LocalDateTime updatedOn) {
+ this.updatedOn = updatedOn;
+ }
+
+ public LocalDateTime getDeleted() {
+ return deleted;
+ }
+
+ public void setDeleted(LocalDateTime deleted) {
+ this.deleted = deleted;
+ }
+
+ public int getSeatBooked() {
+ return seatBooked;
+ }
+
+ public void setSeatBooked(int seatBooked) {
+ this.seatBooked = seatBooked;
+ }
+
+ public String getSeatNumbers() {
+ return seatNumbers;
+ }
+
+ public void setSeatNumbers(String seatNumbers) {
+ this.seatNumbers = seatNumbers;
+ }
+
+ @Override
+ public String toString() {
+ return "Booking [bookingId=" + bookingId + ", userId=" + userId + ", theaterId=" + theaterId + ", paymentId="
+ + paymentId + ", movieId=" + movieId + ", notificationId=" + notificationId + ", totalPrice="
+ + totalPrice + ", createdOn=" + createdOn + ", updatedOn=" + updatedOn + ", deleted=" + deleted
+ + ", seatBooked=" + seatBooked + ", seatNumbers=" + seatNumbers + "]";
+ }
+
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/entity/Cast.java b/src/main/java/com/dummy/bookmyshow/entity/Cast.java
new file mode 100644
index 0000000..095b8c5
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/entity/Cast.java
@@ -0,0 +1,83 @@
+package com.dummy.bookmyshow.entity;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "cast")
+public class Cast implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @Column(name = "id", updatable = false,nullable = false)
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ @Column(name = "cast_id")
+ private String movieId;
+
+ @Column(name = "character_name")
+ private String characterName;
+
+ @Column(name = "character_occupation")
+ private String characterOccupation;
+
+ @Column(name = "description")
+ private String castDetails;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getMovieId() {
+ return movieId;
+ }
+
+ public void setMovieId(String movieId) {
+ this.movieId = movieId;
+ }
+
+ public String getCharacterName() {
+ return characterName;
+ }
+
+ public void setCharacterName(String characterName) {
+ this.characterName = characterName;
+ }
+
+ public String getCharacterOccupation() {
+ return characterOccupation;
+ }
+
+ public void setCharacterOccupation(String characterOccupation) {
+ this.characterOccupation = characterOccupation;
+ }
+
+ public String getCastDetails() {
+ return castDetails;
+ }
+
+ public void setCastDetails(String castDetails) {
+ this.castDetails = castDetails;
+ }
+
+ @Override
+ public String toString() {
+ return "Cast [id=" + id + ", movieId=" + movieId + ", characterName=" + characterName + ", characterOccupation="
+ + characterOccupation + ", castDetails=" + castDetails + "]";
+ }
+
+
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/entity/Movie.java b/src/main/java/com/dummy/bookmyshow/entity/Movie.java
new file mode 100644
index 0000000..f13d3a8
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/entity/Movie.java
@@ -0,0 +1,250 @@
+package com.dummy.bookmyshow.entity;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.format.annotation.DateTimeFormat.ISO;
+
+import com.dummy.bookmyshow.enums.Language;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+@Entity
+@Table(name = "movie")
+public class Movie implements Serializable {
+ private static final long serialVersionUID = -2343243243242432341L;
+ @Id
+ private String movieId;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "type")
+ private String type;
+
+ @Column(name = "language")
+ @Enumerated(EnumType.STRING)
+ private Language language;
+
+ @Column(name = "theater_id")
+ private String theaterId;
+
+ @Column(name = "rating")
+ private String rating;
+
+ @Column(name = "cast_id")
+ private String castId;
+
+ @Column(name = "release_year")
+ private String releaseYear;
+
+ @Column(name = "active_date_start")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime activeDateStart;
+
+ @Column(name = "active_date_end")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime activeDateEnd;
+
+ @Column(name = "trailer_url")
+ private String trailerUrl;
+
+ @Column(name = "poster_url")
+ private String posterUrl;
+
+ @Column(name = "duration")
+ private String duration;
+
+
+ @Column(name = "created_on")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createdOn = LocalDateTime.now();
+
+ @Column(name = "updated_on")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updatedOn;
+
+ @Column(name = "deleted")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime deleted;
+
+ @Column(name = "director")
+ private String director;
+
+ @Column(name = "plot" , length=512)
+ private String plot;
+
+ public String getMovieId() {
+ return movieId;
+ }
+
+ public void setMovieId(String movieId) {
+ this.movieId = movieId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public Language getLanguage() {
+ return language;
+ }
+
+ public void setLanguage(Language language) {
+ this.language = language;
+ }
+
+ public String getTheaterId() {
+ return theaterId;
+ }
+
+ public void setTheaterId(String theaterId) {
+ this.theaterId = theaterId;
+ }
+
+ public String getRating() {
+ return rating;
+ }
+
+ public void setRating(String rating) {
+ this.rating = rating;
+ }
+
+ public String getCastId() {
+ return castId;
+ }
+
+ public void setCastId(String castId) {
+ this.castId = castId;
+ }
+
+ public String getReleaseYear() {
+ return releaseYear;
+ }
+
+ public void setReleaseYear(String releaseYear) {
+ this.releaseYear = releaseYear;
+ }
+
+ public LocalDateTime getActiveDateStart() {
+ return activeDateStart;
+ }
+
+ public void setActiveDateStart(LocalDateTime activeDateStart) {
+ this.activeDateStart = activeDateStart;
+ }
+
+ public LocalDateTime getActiveDateEnd() {
+ return activeDateEnd;
+ }
+
+ public void setActiveDateEnd(LocalDateTime activeDateEnd) {
+ this.activeDateEnd = activeDateEnd;
+ }
+
+ public String getTrailerUrl() {
+ return trailerUrl;
+ }
+
+ public void setTrailerUrl(String trailerUrl) {
+ this.trailerUrl = trailerUrl;
+ }
+
+ public String getPosterUrl() {
+ return posterUrl;
+ }
+
+ public void setPosterUrl(String posterUrl) {
+ this.posterUrl = posterUrl;
+ }
+
+ public String getDuration() {
+ return duration;
+ }
+
+ public void setDuration(String duration) {
+ this.duration = duration;
+ }
+
+ public LocalDateTime getCreatedOn() {
+ return createdOn;
+ }
+
+ public void setCreatedOn(LocalDateTime createdOn) {
+ this.createdOn = createdOn;
+ }
+
+ public LocalDateTime getUpdatedOn() {
+ return updatedOn;
+ }
+
+ public void setUpdatedOn(LocalDateTime updatedOn) {
+ this.updatedOn = updatedOn;
+ }
+
+ public LocalDateTime getDeleted() {
+ return deleted;
+ }
+
+ public void setDeleted(LocalDateTime deleted) {
+ this.deleted = deleted;
+ }
+
+ public String getDirector() {
+ return director;
+ }
+
+ public void setDirector(String director) {
+ this.director = director;
+ }
+
+ public String getPlot() {
+ return plot;
+ }
+
+ public void setPlot(String plot) {
+ this.plot = plot;
+ }
+
+ @Override
+ public String toString() {
+ return "Movie [movieId=" + movieId + ", name=" + name + ", type=" + type + ", language=" + language
+ + ", theaterId=" + theaterId + ", rating=" + rating + ", castId=" + castId + ", releaseYear="
+ + releaseYear + ", activeDateStart=" + activeDateStart + ", activeDateEnd=" + activeDateEnd
+ + ", trailerUrl=" + trailerUrl + ", posterUrl=" + posterUrl + ", duration=" + duration + ", createdOn="
+ + createdOn + ", updatedOn=" + updatedOn + ", deleted=" + deleted + ", director=" + director + ", plot="
+ + plot + "]";
+ }
+
+
+
+
+
+
+
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/entity/Notification.java b/src/main/java/com/dummy/bookmyshow/entity/Notification.java
new file mode 100644
index 0000000..bcbbda7
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/entity/Notification.java
@@ -0,0 +1,195 @@
+package com.dummy.bookmyshow.entity;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.GenericGenerator;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.format.annotation.DateTimeFormat.ISO;
+
+import com.dummy.bookmyshow.enums.NotificationType;
+import com.dummy.bookmyshow.enums.Status;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+@Entity
+@Table(name = "notification")
+public class Notification implements Serializable{
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @GeneratedValue(generator = "uuid2")
+ @GenericGenerator(name = "uuid2", strategy = "uuid2")
+ @Column(name = "notification_id" , columnDefinition = "BINARY(16)")
+ private UUID id;
+
+ @Column(name = "booking_id")
+ private long bookingId;
+
+ @Column(name = "status")
+ @Enumerated(EnumType.STRING)
+ private Status status;
+
+ @Column(name = "receiver_email")
+ private String receiverEmail;
+
+ @Column(name = "receiver_mobile")
+ private String receiverMobileNo;
+
+ @Column(name = "receiver_type")
+ @Enumerated(EnumType.STRING)
+ private NotificationType receiverType;
+
+ @Column(name = "sender_email")
+ private String senderEmail;
+
+ @Column(name = "tiny_url")
+ private String tinyUrl;
+
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @Column(name = "send_timie")
+ private LocalDateTime sendTime;
+
+
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @Column(name = "created_on")
+ private LocalDateTime createdOn = LocalDateTime.now();
+
+
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @Column(name = "updated_on")
+ private LocalDateTime updatedOn = LocalDateTime.now();
+
+
+ public UUID getId() {
+ return id;
+ }
+
+
+ public void setId(UUID id) {
+ this.id = id;
+ }
+
+
+ public long getBookingId() {
+ return bookingId;
+ }
+
+
+ public void setBookingId(long bookingId) {
+ this.bookingId = bookingId;
+ }
+
+
+ public Status getStatus() {
+ return status;
+ }
+
+
+ public void setStatus(Status status) {
+ this.status = status;
+ }
+
+
+ public String getReceiverEmail() {
+ return receiverEmail;
+ }
+
+
+ public void setReceiverEmail(String receiverEmail) {
+ this.receiverEmail = receiverEmail;
+ }
+
+
+ public String getReceiverMobileNo() {
+ return receiverMobileNo;
+ }
+
+
+ public void setReceiverMobileNo(String receiverMobileNo) {
+ this.receiverMobileNo = receiverMobileNo;
+ }
+
+
+ public NotificationType getReceiverType() {
+ return receiverType;
+ }
+
+
+ public void setReceiverType(NotificationType receiverType) {
+ this.receiverType = receiverType;
+ }
+
+
+ public String getSenderEmail() {
+ return senderEmail;
+ }
+
+
+ public void setSenderEmail(String senderEmail) {
+ this.senderEmail = senderEmail;
+ }
+
+
+ public String getTinyUrl() {
+ return tinyUrl;
+ }
+
+
+ public void setTinyUrl(String tinyUrl) {
+ this.tinyUrl = tinyUrl;
+ }
+
+
+ public LocalDateTime getSendTime() {
+ return sendTime;
+ }
+
+
+ public void setSendTime(LocalDateTime sendTime) {
+ this.sendTime = sendTime;
+ }
+
+
+ public LocalDateTime getCreatedOn() {
+ return createdOn;
+ }
+
+
+ public void setCreatedOn(LocalDateTime createdOn) {
+ this.createdOn = createdOn;
+ }
+
+
+ public LocalDateTime getUpdatedOn() {
+ return updatedOn;
+ }
+
+
+ public void setUpdatedOn(LocalDateTime updatedOn) {
+ this.updatedOn = updatedOn;
+ }
+
+
+ @Override
+ public String toString() {
+ return "Notification [id=" + id + ", bookingId=" + bookingId + ", status=" + status + ", receiverEmail="
+ + receiverEmail + ", receiverMobileNo=" + receiverMobileNo + ", receiverType=" + receiverType
+ + ", senderEmail=" + senderEmail + ", tinyUrl=" + tinyUrl + ", sendTime=" + sendTime + ", createdOn="
+ + createdOn + ", updatedOn=" + updatedOn + "]";
+ }
+
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/entity/Offer.java b/src/main/java/com/dummy/bookmyshow/entity/Offer.java
new file mode 100644
index 0000000..b82c9a1
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/entity/Offer.java
@@ -0,0 +1,140 @@
+package com.dummy.bookmyshow.entity;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.format.annotation.DateTimeFormat.ISO;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+@Entity
+@Table(name = "offer")
+public class Offer implements Serializable {
+ private static final long serialVersionUID = 1L;
+ @Id
+ @Column(name = "id", updatable = false,nullable = false)
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "code")
+ private String code;
+
+ @Column(name = "amount_less")
+ private int amountLess;
+
+ @Column(name = "description")
+ private String description;
+
+ @Column(name = "valid_start")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime validStart;
+
+ @Column(name = "valid_end")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime validEnd;
+
+ @Column(name = "created_on")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createdOn = LocalDateTime.now();
+
+ @Column(name = "updated_on")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updatedOn;
+
+ @Column(name = "deleted")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime deleted;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public int getAmountLess() {
+ return amountLess;
+ }
+
+ public void setAmountLess(int amountLess) {
+ this.amountLess = amountLess;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public LocalDateTime getValidStart() {
+ return validStart;
+ }
+
+ public void setValidStart(LocalDateTime validStart) {
+ this.validStart = validStart;
+ }
+
+ public LocalDateTime getValidEnd() {
+ return validEnd;
+ }
+
+ public void setValidEnd(LocalDateTime validEnd) {
+ this.validEnd = validEnd;
+ }
+
+ public LocalDateTime getCreatedOn() {
+ return createdOn;
+ }
+
+ public void setCreatedOn(LocalDateTime createdOn) {
+ this.createdOn = createdOn;
+ }
+
+ public LocalDateTime getUpdatedOn() {
+ return updatedOn;
+ }
+
+ public void setUpdatedOn(LocalDateTime updatedOn) {
+ this.updatedOn = updatedOn;
+ }
+
+ public LocalDateTime getDeleted() {
+ return deleted;
+ }
+
+ public void setDeleted(LocalDateTime deleted) {
+ this.deleted = deleted;
+ }
+
+ @Override
+ public String toString() {
+ return "Offer [id=" + id + ", code=" + code + ", amountLess=" + amountLess + ", description=" + description
+ + ", validStart=" + validStart + ", validEnd=" + validEnd + ", createdOn=" + createdOn + ", updatedOn="
+ + updatedOn + ", deleted=" + deleted + "]";
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/entity/Payment.java b/src/main/java/com/dummy/bookmyshow/entity/Payment.java
new file mode 100644
index 0000000..02294ca
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/entity/Payment.java
@@ -0,0 +1,148 @@
+package com.dummy.bookmyshow.entity;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.hibernate.annotations.GenericGenerator;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.format.annotation.DateTimeFormat.ISO;
+
+import com.dummy.bookmyshow.enums.PaymentMethod;
+import com.dummy.bookmyshow.enums.Status;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+@Entity
+@Table(name = "payment")
+public class Payment implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @GeneratedValue(generator = "uuid2")
+ @GenericGenerator(name = "uuid2", strategy = "uuid2")
+ @Column(name = "transaction_id" , columnDefinition = "BINARY(16)")
+ private UUID id;
+
+
+ @Column(name = "status")
+ @Enumerated(EnumType.STRING)
+ private Status status;
+
+
+ @Column(name = "amount")
+ private int amount;
+
+ @Column(name = "method")
+ @Enumerated(EnumType.STRING)
+ private PaymentMethod method;
+
+ @Column(name = "source_details")
+ private String sourceDetails;
+
+ @Column(name = "booking_id")
+ private Long bookingId;
+
+ @Column(name = "created_on")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createdOn = LocalDateTime.now();
+
+ @Column(name = "updated_on")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updatedOn;
+
+ @Column(name = "deleted")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime deleted;
+
+ public UUID getId() {
+ return id;
+ }
+
+ public void setId(UUID id) {
+ this.id = id;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+ public void setStatus(Status status) {
+ this.status = status;
+ }
+
+ public int getAmount() {
+ return amount;
+ }
+
+ public void setAmount(int amount) {
+ this.amount = amount;
+ }
+
+ public PaymentMethod getMethod() {
+ return method;
+ }
+
+ public void setMethod(PaymentMethod method) {
+ this.method = method;
+ }
+
+ public String getSourceDetails() {
+ return sourceDetails;
+ }
+
+ public void setSourceDetails(String sourceDetails) {
+ this.sourceDetails = sourceDetails;
+ }
+
+ public Long getBookingId() {
+ return bookingId;
+ }
+
+ public void setBookingId(Long bookingId) {
+ this.bookingId = bookingId;
+ }
+
+ public LocalDateTime getCreatedOn() {
+ return createdOn;
+ }
+
+ public void setCreatedOn(LocalDateTime createdOn) {
+ this.createdOn = createdOn;
+ }
+
+ public LocalDateTime getUpdatedOn() {
+ return updatedOn;
+ }
+
+ public void setUpdatedOn(LocalDateTime updatedOn) {
+ this.updatedOn = updatedOn;
+ }
+
+ public LocalDateTime getDeleted() {
+ return deleted;
+ }
+
+ public void setDeleted(LocalDateTime deleted) {
+ this.deleted = deleted;
+ }
+
+ @Override
+ public String toString() {
+ return "Payment [id=" + id + ", status=" + status + ", amount=" + amount + ", method=" + method
+ + ", sourceDetails=" + sourceDetails + ", bookingId=" + bookingId + ", createdOn=" + createdOn
+ + ", updatedOn=" + updatedOn + ", deleted=" + deleted + "]";
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/entity/Screen.java b/src/main/java/com/dummy/bookmyshow/entity/Screen.java
new file mode 100644
index 0000000..748f639
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/entity/Screen.java
@@ -0,0 +1,41 @@
+package com.dummy.bookmyshow.entity;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "screen")
+public class Screen implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ @EmbeddedId
+ private ScreenPk screenDetails;
+
+ @Column(name = "ends_at")
+ private String endsAt;
+
+ public ScreenPk getScreenDetails() {
+ return screenDetails;
+ }
+
+ public void setScreenDetails(ScreenPk screenDetails) {
+ this.screenDetails = screenDetails;
+ }
+
+ public String getEndsAt() {
+ return endsAt;
+ }
+
+ public void setEndsAt(String endsAt) {
+ this.endsAt = endsAt;
+ }
+
+ @Override
+ public String toString() {
+ return "Screen [screenDetails=" + screenDetails + ", endsAt=" + endsAt + "]";
+ }
+}
diff --git a/src/main/java/com/dummy/bookmyshow/entity/ScreenPk.java b/src/main/java/com/dummy/bookmyshow/entity/ScreenPk.java
new file mode 100644
index 0000000..e2180a7
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/entity/ScreenPk.java
@@ -0,0 +1,50 @@
+package com.dummy.bookmyshow.entity;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class ScreenPk implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Column(name = "theater_id", nullable = false)
+ private String theaterId;
+
+ @Column(name = "movie_id", nullable = false)
+ private String movieId;
+
+ @Column(name = "starts_at", nullable = false)
+ private String startsAt;
+
+ public String getTheaterId() {
+ return theaterId;
+ }
+
+ public void setTheaterId(String theaterId) {
+ this.theaterId = theaterId;
+ }
+
+ public String getMovieId() {
+ return movieId;
+ }
+
+ public void setMovieId(String movieId) {
+ this.movieId = movieId;
+ }
+
+ public String getStartsAt() {
+ return startsAt;
+ }
+
+ public void setStartsAt(String startsAt) {
+ this.startsAt = startsAt;
+ }
+
+
+
+
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/entity/SeatMatrix.java b/src/main/java/com/dummy/bookmyshow/entity/SeatMatrix.java
new file mode 100644
index 0000000..70c3fc7
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/entity/SeatMatrix.java
@@ -0,0 +1,115 @@
+package com.dummy.bookmyshow.entity;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Table;
+
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.format.annotation.DateTimeFormat.ISO;
+
+import com.dummy.bookmyshow.enums.SeatType;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+@Entity
+@Table(name = "seat_matrix")
+public class SeatMatrix implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ @EmbeddedId
+ private SeatMatrixPk primaryKey;
+
+
+ @Column(name = "booked")
+ private boolean booked;
+
+ @Column(name = "seat_type")
+ @Enumerated(EnumType.STRING)
+ private SeatType seatType;
+
+ @Column(name = "created_on")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createdOn = LocalDateTime.now();
+
+ @Column(name = "updated_on")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updatedOn;
+
+ @Column(name = "deleted")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime deleted;
+
+ @Column(name = "seat_price")
+ private int price;
+
+ public SeatMatrixPk getPrimaryKey() {
+ return primaryKey;
+ }
+
+ public void setPrimaryKey(SeatMatrixPk primaryKey) {
+ this.primaryKey = primaryKey;
+ }
+
+ public boolean isBooked() {
+ return booked;
+ }
+
+ public void setBooked(boolean booked) {
+ this.booked = booked;
+ }
+
+ public SeatType getSeatType() {
+ return seatType;
+ }
+
+ public void setSeatType(SeatType seatType) {
+ this.seatType = seatType;
+ }
+
+ public LocalDateTime getCreatedOn() {
+ return createdOn;
+ }
+
+ public void setCreatedOn(LocalDateTime createdOn) {
+ this.createdOn = createdOn;
+ }
+
+ public LocalDateTime getUpdatedOn() {
+ return updatedOn;
+ }
+
+ public void setUpdatedOn(LocalDateTime updatedOn) {
+ this.updatedOn = updatedOn;
+ }
+
+ public LocalDateTime getDeleted() {
+ return deleted;
+ }
+
+ public void setDeleted(LocalDateTime deleted) {
+ this.deleted = deleted;
+ }
+
+ public int getPrice() {
+ return price;
+ }
+
+ public void setPrice(int price) {
+ this.price = price;
+ }
+
+ @Override
+ public String toString() {
+ return "SeatMatrix [primaryKey=" + primaryKey + ", booked=" + booked + ", seatType=" + seatType + ", createdOn="
+ + createdOn + ", updatedOn=" + updatedOn + ", deleted=" + deleted + ", price=" + price + "]";
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/entity/SeatMatrixPk.java b/src/main/java/com/dummy/bookmyshow/entity/SeatMatrixPk.java
new file mode 100644
index 0000000..8663423
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/entity/SeatMatrixPk.java
@@ -0,0 +1,63 @@
+package com.dummy.bookmyshow.entity;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class SeatMatrixPk implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Column(name = "movie_id")
+ private String movieId;
+
+ @Column(name = "theater_id")
+ private String theaterId;
+
+ @Column(name = "screen_starts_at")
+ private String screenStartsAt;
+
+ @Column(name = "seat_number", nullable = false)
+ private String seatNumber;
+
+ public String getMovieId() {
+ return movieId;
+ }
+
+ public void setMovieId(String movieId) {
+ this.movieId = movieId;
+ }
+
+ public String getTheaterId() {
+ return theaterId;
+ }
+
+ public void setTheaterId(String theaterId) {
+ this.theaterId = theaterId;
+ }
+
+ public String getScreenStartsAt() {
+ return screenStartsAt;
+ }
+
+ public void setScreenStartsAt(String screenStartsAt) {
+ this.screenStartsAt = screenStartsAt;
+ }
+
+ public String getSeatNumber() {
+ return seatNumber;
+ }
+
+ public void setSeatNumber(String seatNumber) {
+ this.seatNumber = seatNumber;
+ }
+
+ @Override
+ public String toString() {
+ return "SeatMatrixPk [movieId=" + movieId + ", theaterId=" + theaterId + ", screenStartsAt=" + screenStartsAt
+ + ", seatNumber=" + seatNumber + "]";
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/entity/Show.java b/src/main/java/com/dummy/bookmyshow/entity/Show.java
new file mode 100644
index 0000000..18dcfc9
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/entity/Show.java
@@ -0,0 +1,80 @@
+//package com.dummy.bookmyshow.entity;
+//
+//import java.io.Serializable;
+//import java.util.Date;
+//
+//import javax.persistence.Column;
+//import javax.persistence.Entity;
+//import javax.persistence.GeneratedValue;
+//import javax.persistence.GenerationType;
+//import javax.persistence.Id;
+//import javax.persistence.Table;
+//import javax.persistence.Temporal;
+//import javax.persistence.TemporalType;
+//
+//@Entity
+//@Table(name = "shows")
+//public class Show implements Serializable {
+//
+// private static final long serialVersionUID = 1L;
+// @Id
+// @Column(name = "id", updatable = false, nullable = false)
+// @GeneratedValue(strategy = GenerationType.IDENTITY)
+// private Long id;
+//
+// @Column(name = "movie_id")
+// private Long movieId;
+//
+//// @Column(name = "theater_id")
+//// private Long theaterId;
+////
+//// @Column(name = "screen_id")
+//// private Long screenId;
+//
+// @Column(name = "starts_at", columnDefinition = "DATETIME")
+// @Temporal(TemporalType.DATE)
+// private Date startsAt;
+//
+// @Column(name = "ends_at", columnDefinition = "DATETIME")
+// @Temporal(TemporalType.DATE)
+//
+// private Date endsAt;
+//
+// public Long getId() {
+// return id;
+// }
+//
+// public void setId(Long id) {
+// this.id = id;
+// }
+//
+// public Long getMovieId() {
+// return movieId;
+// }
+//
+// public void setMovieId(Long movieId) {
+// this.movieId = movieId;
+// }
+//
+// public Date getStartsAt() {
+// return startsAt;
+// }
+//
+// public void setStartsAt(Date startsAt) {
+// this.startsAt = startsAt;
+// }
+//
+// public Date getEndsAt() {
+// return endsAt;
+// }
+//
+// public void setEndsAt(Date endsAt) {
+// this.endsAt = endsAt;
+// }
+//
+// @Override
+// public String toString() {
+// return "Show [id=" + id + ", movieId=" + movieId + ", startsAt=" + startsAt + ", endsAt=" + endsAt + "]";
+// }
+//
+//}
diff --git a/src/main/java/com/dummy/bookmyshow/entity/Theater.java b/src/main/java/com/dummy/bookmyshow/entity/Theater.java
new file mode 100644
index 0000000..6c950f0
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/entity/Theater.java
@@ -0,0 +1,158 @@
+package com.dummy.bookmyshow.entity;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.format.annotation.DateTimeFormat.ISO;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+@Entity
+@Table(name = "theater")
+public class Theater implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ @Id
+ @Column(name = "theater_id")
+ private String theaterId;
+
+ @Column(name = "address")
+ private String address;
+
+ @Column(name = "city")
+ private String city;
+
+ @Column(name = "country")
+ private String country;
+
+ @Column(name = "name")
+ private String name;
+
+ @Column(name = "languages")
+ private String languages;
+
+ @Column(name = "created_on")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createdOn = LocalDateTime.now() ;
+
+ @Column(name = "updated_on")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updatedOn;
+
+ @Column(name = "deleted")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime deleted;
+
+ @Column(name = "user_name")
+ private String userName;
+
+ public Theater() {};
+
+ public Theater(String theaterId, String address, String city, String country, String name, String languages, String userName) {
+ super();
+ this.theaterId = theaterId;
+ this.address = address;
+ this.city = city;
+ this.country = country;
+ this.name = name;
+ this.languages = languages;
+ this.userName = userName;
+ }
+
+ public String getTheaterId() {
+ return theaterId;
+ }
+
+ public void setTheaterId(String theaterId) {
+ this.theaterId = theaterId;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getLanguages() {
+ return languages;
+ }
+
+ public void setLanguages(String languages) {
+ this.languages = languages;
+ }
+
+ public LocalDateTime getCreatedOn() {
+ return createdOn;
+ }
+
+ public void setCreatedOn(LocalDateTime createdOn) {
+ this.createdOn = createdOn;
+ }
+
+ public LocalDateTime getUpdatedOn() {
+ return updatedOn;
+ }
+
+ public void setUpdatedOn(LocalDateTime updatedOn) {
+ this.updatedOn = updatedOn;
+ }
+
+ public LocalDateTime getDeleted() {
+ return deleted;
+ }
+
+ public void setDeleted(LocalDateTime deleted) {
+ this.deleted = deleted;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ @Override
+ public String toString() {
+ return "Theater [theaterId=" + theaterId + ", address=" + address + ", city=" + city + ", country=" + country
+ + ", name=" + name + ", languages=" + languages + ", createdOn=" + createdOn + ", updatedOn="
+ + updatedOn + ", deleted=" + deleted + ", userName=" + userName + "]";
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/entity/Url.java b/src/main/java/com/dummy/bookmyshow/entity/Url.java
new file mode 100644
index 0000000..7e411af
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/entity/Url.java
@@ -0,0 +1,61 @@
+package com.dummy.bookmyshow.entity;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "url")
+public class Url implements Serializable{
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @Column(name = "url_id", updatable = false, nullable = false)
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "original_url")
+ private String originalUrl;
+
+ @Column(name = "created_on")
+ private LocalDateTime createdOn = LocalDateTime.now();
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getOriginalUrl() {
+ return originalUrl;
+ }
+
+ public void setOriginalUrl(String originalUrl) {
+ this.originalUrl = originalUrl;
+ }
+
+ public LocalDateTime getCreatedOn() {
+ return createdOn;
+ }
+
+ public void setCreatedOn(LocalDateTime createdOn) {
+ this.createdOn = createdOn;
+ }
+
+ @Override
+ public String toString() {
+ return "Url [id=" + id + ", originalUrl=" + originalUrl + ", createdOn=" + createdOn + "]";
+ }
+
+
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/entity/User.java b/src/main/java/com/dummy/bookmyshow/entity/User.java
new file mode 100644
index 0000000..78454cf
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/entity/User.java
@@ -0,0 +1,155 @@
+package com.dummy.bookmyshow.entity;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.format.annotation.DateTimeFormat.ISO;
+
+import com.dummy.bookmyshow.enums.UserType;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+@Entity
+@Table(name = "user")
+public class User implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Column(name = "first_name", nullable = false)
+ private String firstName;
+
+ @Column(name = "last_name", nullable = false)
+ private String lastName;
+
+ @Column(name = "mobile_number", nullable = false)
+ private String mobileNumber;
+
+ @Column(name = "user_type")
+ @Enumerated(EnumType.STRING)
+ private UserType userType;
+
+ @Column(name = "email")
+ private String email;
+
+ @Id
+ @Column(name = "user_name",nullable = false) //we will generate username from name
+ private String userName;
+
+ @Column(name = "authentication")
+ private String authentication; // store the password
+
+ @Column(name = "created_on")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createdOn = LocalDateTime.now();
+
+ @Column(name = "updated_on")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updatedOn;
+
+ @Column(name = "deleted")
+ @DateTimeFormat(iso = ISO.DATE_TIME)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime deleted;
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public String getMobileNumber() {
+ return mobileNumber;
+ }
+
+ public void setMobileNumber(String mobileNumber) {
+ this.mobileNumber = mobileNumber;
+ }
+
+ public UserType getUserType() {
+ return userType;
+ }
+
+ public void setUserType(UserType userType) {
+ this.userType = userType;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getAuthentication() {
+ return authentication;
+ }
+
+ public void setAuthentication(String authentication) {
+ this.authentication = authentication;
+ }
+
+ public LocalDateTime getCreatedOn() {
+ return createdOn;
+ }
+
+ public void setCreatedOn(LocalDateTime createdOn) {
+ this.createdOn = createdOn;
+ }
+
+ public LocalDateTime getUpdatedOn() {
+ return updatedOn;
+ }
+
+ public void setUpdatedOn(LocalDateTime updatedOn) {
+ this.updatedOn = updatedOn;
+ }
+
+ public LocalDateTime getDeleted() {
+ return deleted;
+ }
+
+ public void setDeleted(LocalDateTime deleted) {
+ this.deleted = deleted;
+ }
+
+ @Override
+ public String toString() {
+ return "User [firstName=" + firstName + ", lastName=" + lastName + ", mobileNumber=" + mobileNumber
+ + ", userType=" + userType + ", email=" + email + ", userName=" + userName + ", authentication="
+ + authentication + ", createdOn=" + createdOn + ", updatedOn=" + updatedOn + ", deleted=" + deleted
+ + "]";
+ }
+
+
+
+
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/entity/UserPrimaryKey.java b/src/main/java/com/dummy/bookmyshow/entity/UserPrimaryKey.java
new file mode 100644
index 0000000..08ce00c
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/entity/UserPrimaryKey.java
@@ -0,0 +1,37 @@
+//package com.dummy.bookmyshow.entity;
+//
+//import java.io.Serializable;
+//
+//import javax.persistence.Column;
+//import javax.persistence.Embeddable;
+//
+//@Embeddable
+//public class UserPrimaryKey implements Serializable {
+// private static final long serialVersionUID = 1L;
+// @Column(name = "name", nullable = false)
+// private String name;
+// @Column(name = "mobile_number", nullable = false)
+// private String mobileNumber;
+//
+// public String getName() {
+// return name;
+// }
+//
+// public void setName(String name) {
+// this.name = name;
+// }
+//
+// public String getMobileNumber() {
+// return mobileNumber;
+// }
+//
+// public void setMobileNumber(String mobileNumber) {
+// this.mobileNumber = mobileNumber;
+// }
+//
+// @Override
+// public String toString() {
+// return "UserPrimaryKey [name=" + name + ", mobileNumber=" + mobileNumber + "]";
+// }
+//
+//}
diff --git a/src/main/java/com/dummy/bookmyshow/enums/Language.java b/src/main/java/com/dummy/bookmyshow/enums/Language.java
new file mode 100644
index 0000000..6285bcb
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/enums/Language.java
@@ -0,0 +1,6 @@
+package com.dummy.bookmyshow.enums;
+
+public enum Language {
+ HINDI, ENGLISH
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/enums/MovieType.java b/src/main/java/com/dummy/bookmyshow/enums/MovieType.java
new file mode 100644
index 0000000..820d669
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/enums/MovieType.java
@@ -0,0 +1,5 @@
+package com.dummy.bookmyshow.enums;
+
+public enum MovieType {
+ COMEDY, CRIME, SUSPENSE, ROMANCE, THILLER
+}
diff --git a/src/main/java/com/dummy/bookmyshow/enums/NotificationType.java b/src/main/java/com/dummy/bookmyshow/enums/NotificationType.java
new file mode 100644
index 0000000..c1ea4c6
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/enums/NotificationType.java
@@ -0,0 +1,5 @@
+package com.dummy.bookmyshow.enums;
+
+public enum NotificationType {
+MOBILEPHONE,EMAIL,WATSAPP
+}
diff --git a/src/main/java/com/dummy/bookmyshow/enums/PaymentMethod.java b/src/main/java/com/dummy/bookmyshow/enums/PaymentMethod.java
new file mode 100644
index 0000000..8c7acbb
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/enums/PaymentMethod.java
@@ -0,0 +1,5 @@
+package com.dummy.bookmyshow.enums;
+
+public enum PaymentMethod {
+ CREDITCARD, DEBITCARD, INTERNETBANKING, PAYTM, AMAZONPAY, UPI
+}
diff --git a/src/main/java/com/dummy/bookmyshow/enums/SeatType.java b/src/main/java/com/dummy/bookmyshow/enums/SeatType.java
new file mode 100644
index 0000000..88f7952
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/enums/SeatType.java
@@ -0,0 +1,5 @@
+package com.dummy.bookmyshow.enums;
+
+public enum SeatType {
+ NORMAL, VIP, EXECUTIVE, ROYAL, ENCLINER
+}
diff --git a/src/main/java/com/dummy/bookmyshow/enums/Status.java b/src/main/java/com/dummy/bookmyshow/enums/Status.java
new file mode 100644
index 0000000..28a7f2d
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/enums/Status.java
@@ -0,0 +1,6 @@
+package com.dummy.bookmyshow.enums;
+
+public enum Status {
+ SUCCESS,FAILED,PROCESSING
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/enums/TheaterType.java b/src/main/java/com/dummy/bookmyshow/enums/TheaterType.java
new file mode 100644
index 0000000..b3852d6
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/enums/TheaterType.java
@@ -0,0 +1,5 @@
+package com.dummy.bookmyshow.enums;
+
+public enum TheaterType {
+ IMAX, PVR, LOCAL
+}
diff --git a/src/main/java/com/dummy/bookmyshow/enums/UserType.java b/src/main/java/com/dummy/bookmyshow/enums/UserType.java
new file mode 100644
index 0000000..e634979
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/enums/UserType.java
@@ -0,0 +1,5 @@
+package com.dummy.bookmyshow.enums;
+
+public enum UserType {
+ADMIN,NORMAL
+}
diff --git a/src/main/java/com/dummy/bookmyshow/repository/BookingRepository.java b/src/main/java/com/dummy/bookmyshow/repository/BookingRepository.java
new file mode 100644
index 0000000..0b7ba9a
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/repository/BookingRepository.java
@@ -0,0 +1,11 @@
+package com.dummy.bookmyshow.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import com.dummy.bookmyshow.entity.Booking;
+
+@Repository
+public interface BookingRepository extends JpaRepository {
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/repository/CastRepository.java b/src/main/java/com/dummy/bookmyshow/repository/CastRepository.java
new file mode 100644
index 0000000..ef00f1c
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/repository/CastRepository.java
@@ -0,0 +1,17 @@
+package com.dummy.bookmyshow.repository;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import com.dummy.bookmyshow.entity.Cast;
+
+@Repository
+public interface CastRepository extends JpaRepository{
+ @Query(value = "select * from cast where movie_id=:movieId", nativeQuery=true)
+ List getCastByMovieId(@Param("movieId") String movieId);
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/repository/MovieRepository.java b/src/main/java/com/dummy/bookmyshow/repository/MovieRepository.java
new file mode 100644
index 0000000..3ab73ef
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/repository/MovieRepository.java
@@ -0,0 +1,20 @@
+package com.dummy.bookmyshow.repository;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import com.dummy.bookmyshow.entity.Movie;
+
+@Repository
+public interface MovieRepository extends JpaRepository
+{
+
+
+ @Query(value = "select m.* from movie m join theater t on t.theater_id = m.theater_id and t.city = :city", nativeQuery = true)
+ List getAvailableMovies(@Param("city")String city);
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/repository/NotificationRepository.java b/src/main/java/com/dummy/bookmyshow/repository/NotificationRepository.java
new file mode 100644
index 0000000..37a8088
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/repository/NotificationRepository.java
@@ -0,0 +1,13 @@
+package com.dummy.bookmyshow.repository;
+
+import java.util.UUID;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import com.dummy.bookmyshow.entity.Notification;
+
+@Repository
+public interface NotificationRepository extends JpaRepository{
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/repository/PaymentRepository.java b/src/main/java/com/dummy/bookmyshow/repository/PaymentRepository.java
new file mode 100644
index 0000000..dd58976
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/repository/PaymentRepository.java
@@ -0,0 +1,13 @@
+package com.dummy.bookmyshow.repository;
+
+import java.util.UUID;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import com.dummy.bookmyshow.entity.Payment;
+
+@Repository
+public interface PaymentRepository extends JpaRepository{
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/repository/ScreenRepository.java b/src/main/java/com/dummy/bookmyshow/repository/ScreenRepository.java
new file mode 100644
index 0000000..5c809de
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/repository/ScreenRepository.java
@@ -0,0 +1,19 @@
+package com.dummy.bookmyshow.repository;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import com.dummy.bookmyshow.entity.Screen;
+import com.dummy.bookmyshow.entity.ScreenPk;
+
+@Repository
+public interface ScreenRepository extends JpaRepository {
+
+ @Query(value = " select * from screen where theater_id=:theaterId and movie_id = :movieId", nativeQuery = true)
+ List findScreenByTheaterIdAndMovieId(@Param("theaterId") String theaterId, @Param("movieId") String movieId);
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/repository/SeatMatrixRepository.java b/src/main/java/com/dummy/bookmyshow/repository/SeatMatrixRepository.java
new file mode 100644
index 0000000..aa191a6
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/repository/SeatMatrixRepository.java
@@ -0,0 +1,20 @@
+package com.dummy.bookmyshow.repository;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import com.dummy.bookmyshow.entity.SeatMatrix;
+import com.dummy.bookmyshow.entity.SeatMatrixPk;
+
+@Repository
+public interface SeatMatrixRepository extends JpaRepository {
+
+ @Query(value = "select * from seat_matrix where movie_id = :movieId and theater_id=:theaterId and screen_starts_at = :screenStartsAt and booked = false ", nativeQuery = true)
+ List getSeatMatrixForscreen(@Param("movieId")String movieId, @Param("theaterId")String theaterId, @Param
+ ("screenStartsAt") String screenStartsAt);
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/repository/TheaterRepository.java b/src/main/java/com/dummy/bookmyshow/repository/TheaterRepository.java
new file mode 100644
index 0000000..940e4c4
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/repository/TheaterRepository.java
@@ -0,0 +1,20 @@
+package com.dummy.bookmyshow.repository;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import com.dummy.bookmyshow.entity.Theater;
+@Repository
+public interface TheaterRepository extends JpaRepository {
+
+ @Query(value = "select distinct(city) from theater", nativeQuery = true)
+ List getSupportdCities();
+
+ @Query(value = "select * from theater where theater_id = :theaterId and city = :city", nativeQuery = true)
+ List getScreensShowingMovie(@Param("theaterId")String theaterId, @Param("city")String city);
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/repository/UrlRepository.java b/src/main/java/com/dummy/bookmyshow/repository/UrlRepository.java
new file mode 100644
index 0000000..b5f7eb0
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/repository/UrlRepository.java
@@ -0,0 +1,11 @@
+package com.dummy.bookmyshow.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import com.dummy.bookmyshow.entity.Url;
+
+@Repository
+public interface UrlRepository extends JpaRepository{
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/repository/UserRepository.java b/src/main/java/com/dummy/bookmyshow/repository/UserRepository.java
new file mode 100644
index 0000000..2f228ac
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/repository/UserRepository.java
@@ -0,0 +1,18 @@
+package com.dummy.bookmyshow.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import com.dummy.bookmyshow.entity.User;
+@Repository
+public interface UserRepository extends JpaRepository
+{
+
+ @Query(value = "select * from user where user_name = :userName", nativeQuery = true)
+ User findUserByUserName(@Param("userName") String userName);
+
+
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/security/AuthRequest.java b/src/main/java/com/dummy/bookmyshow/security/AuthRequest.java
new file mode 100644
index 0000000..07e0862
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/security/AuthRequest.java
@@ -0,0 +1,33 @@
+package com.dummy.bookmyshow.security;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class AuthRequest {
+
+ @JsonProperty
+ private String username;
+ @JsonProperty
+ private String password;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ @Override
+ public String toString() {
+ return "AuthRequest [username=" + username + ", password=" + password + "]";
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/dummy/bookmyshow/security/CustomUserDetailService.java b/src/main/java/com/dummy/bookmyshow/security/CustomUserDetailService.java
new file mode 100644
index 0000000..8544d2c
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/security/CustomUserDetailService.java
@@ -0,0 +1,27 @@
+package com.dummy.bookmyshow.security;
+
+import java.util.ArrayList;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+
+import com.dummy.bookmyshow.entity.User;
+import com.dummy.bookmyshow.repository.UserRepository;
+
+@Service
+public class CustomUserDetailService implements UserDetailsService {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Override
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+ User user = this.userRepository.findUserByUserName(username);
+ return new org.springframework.security.core.userdetails.User(user.getUserName(), user.getAuthentication(),
+ new ArrayList<>());
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/security/JwtFilter.java b/src/main/java/com/dummy/bookmyshow/security/JwtFilter.java
new file mode 100644
index 0000000..fa11413
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/security/JwtFilter.java
@@ -0,0 +1,53 @@
+package com.dummy.bookmyshow.security;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+@Component
+public class JwtFilter extends OncePerRequestFilter {
+ @Autowired
+ private JwtUtils jwtUtils;
+
+ @Autowired
+ private CustomUserDetailService customUserDetailService;
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+ throws ServletException, IOException {
+ String authorizationHeader = request.getHeader("Authorization");
+ String token = null;
+ String userName = null;
+
+ if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
+ token = authorizationHeader.substring(7);
+ userName = jwtUtils.extractUsername(token);
+ }
+ if (userName != null && SecurityContextHolder.getContext().getAuthentication() == null) {
+
+ UserDetails userDetails = customUserDetailService.loadUserByUsername(userName);
+
+ if (jwtUtils.validateToken(token, userDetails)) {
+
+ UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
+ userDetails, null, userDetails.getAuthorities());
+ usernamePasswordAuthenticationToken
+ .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+ SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
+ }
+ }
+ filterChain.doFilter(request, response);
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/security/JwtUtils.java b/src/main/java/com/dummy/bookmyshow/security/JwtUtils.java
new file mode 100644
index 0000000..a84d609
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/security/JwtUtils.java
@@ -0,0 +1,55 @@
+package com.dummy.bookmyshow.security;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Service;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+
+@Service
+public class JwtUtils {
+ private String secret = "bookmyshow";
+
+ public String extractUsername(String token) {
+ return extractClaim(token, Claims::getSubject);
+ }
+
+ public Date extractExpiration(String token) {
+ return extractClaim(token, Claims::getExpiration);
+ }
+
+ public T extractClaim(String token, Function claimsResolver) {
+ final Claims claims = extractAllClaims(token);
+ return claimsResolver.apply(claims);
+ }
+ private Claims extractAllClaims(String token) {
+ return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
+ }
+
+ private Boolean isTokenExpired(String token) {
+ return extractExpiration(token).before(new Date());
+ }
+
+ public String generateToken(String username) {
+ Map claims = new HashMap<>();
+ return createToken(claims, username);
+ }
+
+ private String createToken(Map claims, String subject) {
+
+ return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
+ .setExpiration(new Date(System.currentTimeMillis() + 72000000000L))
+ .signWith(SignatureAlgorithm.HS256, secret).compact();
+ }
+
+ public Boolean validateToken(String token, UserDetails userDetails) {
+ final String username = extractUsername(token);
+ return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
+ }
+}
diff --git a/src/main/java/com/dummy/bookmyshow/security/SecurityConfig.java b/src/main/java/com/dummy/bookmyshow/security/SecurityConfig.java
new file mode 100644
index 0000000..14fcab9
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/security/SecurityConfig.java
@@ -0,0 +1,62 @@
+package com.dummy.bookmyshow.security;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.BeanIds;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.password.NoOpPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+@Configuration
+@EnableWebSecurity
+public class SecurityConfig extends WebSecurityConfigurerAdapter{
+
+ @Autowired
+ private CustomUserDetailService customuserDetailService;
+ @Autowired
+ private JwtFilter jwtFilter;
+
+
+ @Override
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+ auth.userDetailsService(customuserDetailService);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return NoOpPasswordEncoder.getInstance();
+ }
+
+ @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
+ @Override
+ public AuthenticationManager authenticationManagerBean() throws Exception {
+ return super.authenticationManagerBean();
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.csrf().disable().authorizeRequests()
+ .antMatchers("/v1/**").permitAll()
+ // .antMatchers("/api").permitAll()
+ .antMatchers("/swagger-ui.html").permitAll()
+ .antMatchers("/v1/token").permitAll()
+ .antMatchers("/css/**").permitAll()
+ .antMatchers("/js/**").permitAll()
+ .antMatchers("/favicon.ico").permitAll()
+
+ //TODO : uncomment below line if you want to authenticate
+ // .antMatchers("/v1/**").hasIpAddress(ip)
+ //.anyRequest().authenticated().and().exceptionHandling()
+ .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
+ http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/service/impl/CastServiceImpl.java b/src/main/java/com/dummy/bookmyshow/service/impl/CastServiceImpl.java
new file mode 100644
index 0000000..5552092
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/service/impl/CastServiceImpl.java
@@ -0,0 +1,45 @@
+package com.dummy.bookmyshow.service.impl;
+
+import java.util.List;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.dummy.bookmyshow.entity.Cast;
+import com.dummy.bookmyshow.repository.CastRepository;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Service
+public class CastServiceImpl {
+ private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
+
+ @Autowired
+ private CastRepository castRepo;
+
+ /**
+ * The service method will return the casts for a movie, it will query the DB for movieId
+ * @param movieId
+ * @return
+ * @throws JsonProcessingException
+ */
+ public JSONArray findByMovieId(String movieId) throws JsonProcessingException {
+ this.LOGGER.info("findByMovieId() cast service called with input " + movieId);
+ List casts = this.castRepo.getCastByMovieId(movieId);
+ this.LOGGER.info("findByMovieId() Found " + casts.size() + " no of casts for movie " + movieId);
+ JSONArray result = new JSONArray();
+ for (Cast cast : casts) {
+ ObjectMapper mapper = new ObjectMapper();
+ String castString = mapper.writeValueAsString(cast);
+ JSONObject object = new JSONObject(castString);
+ result.put(object);
+ }
+ this.LOGGER.info("findByMovieId() Successfully returned the casts for the movie " + movieId);
+ return result;
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/service/impl/GenericServiceImpl.java b/src/main/java/com/dummy/bookmyshow/service/impl/GenericServiceImpl.java
new file mode 100644
index 0000000..03e2bf0
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/service/impl/GenericServiceImpl.java
@@ -0,0 +1,344 @@
+package com.dummy.bookmyshow.service.impl;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Optional;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.dummy.bookmyshow.entity.Booking;
+import com.dummy.bookmyshow.entity.Movie;
+import com.dummy.bookmyshow.entity.Notification;
+import com.dummy.bookmyshow.entity.Payment;
+import com.dummy.bookmyshow.entity.Screen;
+import com.dummy.bookmyshow.entity.SeatMatrix;
+import com.dummy.bookmyshow.entity.Theater;
+import com.dummy.bookmyshow.entity.Url;
+import com.dummy.bookmyshow.entity.User;
+import com.dummy.bookmyshow.enums.NotificationType;
+import com.dummy.bookmyshow.enums.PaymentMethod;
+import com.dummy.bookmyshow.enums.Status;
+import com.dummy.bookmyshow.repository.BookingRepository;
+import com.dummy.bookmyshow.repository.MovieRepository;
+import com.dummy.bookmyshow.repository.NotificationRepository;
+import com.dummy.bookmyshow.repository.PaymentRepository;
+import com.dummy.bookmyshow.repository.ScreenRepository;
+import com.dummy.bookmyshow.repository.SeatMatrixRepository;
+import com.dummy.bookmyshow.repository.TheaterRepository;
+import com.dummy.bookmyshow.repository.UserRepository;
+import com.dummy.bookmyshow.util.DummyBookMyShowException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@Service
+public class GenericServiceImpl {
+ private static final String DO_NOT_REPLY_DUMMY_BMS_COM = "doNotReply@dummy.bms.com";
+
+ @Autowired
+ private TheaterRepository theaterRepo;
+
+ @Autowired
+ private MovieRepository movieRepo;
+
+ @Autowired
+ private ScreenRepository screenRepo;
+
+ @Autowired
+ private SeatMatrixRepository matrixRepository;
+
+ @Autowired
+ private BookingRepository bookingRepository;
+
+ @Autowired
+ private PaymentRepository paymentRepository;
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Autowired
+ private UrlServiceImpl urlService;
+
+ @Autowired
+ private NotificationRepository notificationRepo;
+
+ private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
+
+ public List getSupportedCities() {
+ return this.theaterRepo.getSupportdCities();
+ }
+
+ /**
+ * This service method will return available movies in a city
+ *
+ * @param city
+ * @return
+ * @throws JsonProcessingException
+ */
+ public JSONArray getAvailableMovies(String city) throws JsonProcessingException {
+ this.LOGGER.info("getAvailableMovies() called in generic service with city: " + city);
+ List availableMovies = this.movieRepo.getAvailableMovies(city);
+ this.LOGGER.info("getAvailableMovies() got " + availableMovies.size() + " movies in city: " + city);
+ JSONArray result = new JSONArray();
+ for (Movie movie : availableMovies) {
+ ObjectMapper mapper = new ObjectMapper();
+ String movieJson = mapper.writeValueAsString(movie);
+ JSONObject obj = new JSONObject(movieJson);
+ obj.put("updatedOn", movie.getUpdatedOn().toString());
+ obj.put("createdOn", movie.getCreatedOn().toString());
+ obj.put("activeDateStart", movie.getActiveDateStart().toString());
+ obj.put("activeDateEnd", movie.getActiveDateEnd());
+
+ result.put(obj);
+ }
+ this.LOGGER.info("getAvailableMovies() successfully returned the movies in city: " + city);
+ return result;
+ }
+
+ /**
+ * This service method will return the screen details for a city which are
+ * showing a movie below is the returned format of JSON:
+ *
+ * { "movieId1": [ { "screens1": true }, { "screens2": true } ] }
+ *
+ * @param movie
+ * @param city
+ * @return
+ * @throws JsonProcessingException
+ */
+ public JSONObject getScreensShowingMovie(String theaterId, String movieId, String city)
+ throws JsonProcessingException {
+ this.LOGGER.info(
+ "getScreensShowingMovie() getting screens which are showing movie : " + movieId + " in city: " + city);
+ List theatersShowingThisMovie = this.theaterRepo.getScreensShowingMovie(theaterId, city);
+ this.LOGGER.info("getScreensShowingMovie() got " + theatersShowingThisMovie.size()
+ + " screens which are showing movie : " + movieId + " in city: " + city);
+ JSONObject result = new JSONObject();
+ for (Theater theater : theatersShowingThisMovie) {
+ List screens = this.screenRepo.findScreenByTheaterIdAndMovieId(theater.getTheaterId(), movieId);
+ JSONArray screensArray = new JSONArray();
+ for (Screen screen : screens) {
+ ObjectMapper mapper = new ObjectMapper();
+ String screenJsonObj = mapper.writeValueAsString(screen);
+ JSONObject obj = new JSONObject(screenJsonObj);
+ screensArray.put(obj);
+ }
+ result.put(movieId, screensArray);
+
+ }
+ this.LOGGER.info(
+ "getScreensShowingMovie() successfully returned screens for movie : " + movieId + " in city: " + city);
+ return result;
+
+ }
+
+ /**
+ * [ { "seat1A": { "availability": true, "type": "royal" } }, { "seat1A": {
+ * "availability": true, "type": "royal" } } ]
+ *
+ * @param screen
+ * @return
+ * @throws JsonProcessingException
+ */
+ public JSONArray getSeatMatrix(String movieId, String theaterId, String screenStartsAt)
+ throws JsonProcessingException {
+ this.LOGGER.info("getSeatMatrix() : getting available seats for theater : " + theaterId + " movieId: "
+ + movieId + " and start time: " + screenStartsAt);
+ List seatsMatrix = this.matrixRepository.getSeatMatrixForscreen(movieId, theaterId, screenStartsAt);
+ JSONArray result = new JSONArray();
+ this.LOGGER.info("getSeatMatrix() : result size for available seats for theater : " + theaterId + " movieId: "
+ + movieId + " and start time: " + screenStartsAt + " is " + seatsMatrix.size());
+ for (SeatMatrix seat : seatsMatrix) {
+ ObjectMapper mapper = new ObjectMapper();
+ String seatJson = mapper.writeValueAsString(seat);
+ JSONObject obj = new JSONObject(seatJson);
+ obj.put("createdOn", seat.getCreatedOn().toString());
+ obj.put("theaterId", seat.getPrimaryKey().getTheaterId());
+ obj.put("movieId", seat.getPrimaryKey().getMovieId());
+ obj.put("seatNumber", seat.getPrimaryKey().getSeatNumber());
+ obj.put("ShowStartsAt", seat.getPrimaryKey().getScreenStartsAt());
+ if (obj.has("primaryKey"))
+ obj.remove("primaryKey");
+ result.put(obj);
+ }
+ this.LOGGER.info("getSeatMatrix() : successfully got available seats for theater : " + theaterId
+ + " movieId: " + movieId + " and start time: " + screenStartsAt);
+ return result;
+ }
+
+ /**
+ * This service method will be responsible for below things: 1. Check if the
+ * seats are already booked, if no then book these seats for this user in this
+ * theater for this movie 2. do the payment , dummy payment details 3. if
+ * payment is success then send the notification related to tickets 4. if
+ * payment not success then mark booked seats as unbook , we can also book the
+ * seats only if the payment is success but since there is a dummy payment data
+ * here so I am just booking seats irrespective of payment status 5. return the
+ * booking details to user 6. I am generating a tiny URL and that URL to user so
+ * that user can retrieve the tickets
+ *
+ * Instead of making whole method synchronized , I have made logic of method
+ * synchronized to improve performance Why block of this method synchronized: so
+ * that not more than 2 threads can access it same time. But for now whole logic
+ * is inside synchronized block
+ *
+ * @param seatsToBook
+ * @param userName
+ * @return
+ * @throws JsonProcessingException
+ * @throws JSONException
+ */
+ public JSONObject bookSeats(List seatsToBook, String userName)
+ throws JSONException, JsonProcessingException {
+ StringBuilder sb = new StringBuilder();
+ /**
+ * TODO : move some of the logic out side synchronized block to optimize
+ * performance
+ */
+ synchronized (seatsToBook) {
+
+ this.LOGGER.info("bookSeats() serivce for username: " + userName);
+ int totalPrice = 0;
+ // update seat matrix first
+ for (SeatMatrix seat : seatsToBook) {
+ Optional seatFromDb = this.matrixRepository.findById(seat.getPrimaryKey());
+ SeatMatrix oSeatMatrix = seatFromDb.get();
+ if (oSeatMatrix != null && oSeatMatrix.isBooked()) {
+ throw new DummyBookMyShowException(
+ "The seat number: " + seat.getPrimaryKey().getSeatNumber() + " is already booked");
+ }
+ oSeatMatrix.setBooked(true);
+ totalPrice += oSeatMatrix.getPrice();
+ this.matrixRepository.save(oSeatMatrix);
+ sb.append(seat.getPrimaryKey().getSeatNumber() + " ,");
+ }
+ String seatNumbers = sb.toString();
+ seatNumbers = (seatNumbers.endsWith(",")) ? seatNumbers.substring(0, seatNumbers.length() - 2)
+ : seatNumbers;
+ this.LOGGER.info("bookSeats() seats booked are " + seatNumbers);
+ this.LOGGER.info("Initiating the payment for this booking....This will be with dummy data.");
+ /**
+ * TODO : apply the offer codes if applicable TODO : update the booking table
+ * for the user , this is for booking history
+ */
+ SeatMatrix seat = seatsToBook.get(0);
+ Booking booking = new Booking();
+ booking.setCreatedOn(LocalDateTime.now());
+ booking.setUserId(userName);
+ booking.setMovieId(seat.getPrimaryKey().getMovieId());
+ booking.setTheaterId(seat.getPrimaryKey().getTheaterId());
+ booking.setSeatBooked(seatsToBook.size());
+ booking.setSeatNumbers(seatNumbers);
+ booking.setTotalPrice(totalPrice);
+ this.bookingRepository.save(booking);
+ this.LOGGER.info("bookSeats() saved booking history.....");
+ /**
+ * payment
+ */
+ Payment dummyPayment = doPayment(booking);
+ // update payment id in booking
+ booking.setPaymentId(dummyPayment.getId());
+ booking.setUpdatedOn(LocalDateTime.now());
+ this.bookingRepository.save(booking);
+ this.LOGGER.info("bookSeats() updated payment id in booking");
+
+ // send the notification and update the notification id in booking table
+ User user = this.userRepository.findUserByUserName(booking.getUserId());
+ if (user == null)
+ throw new DummyBookMyShowException("There is no user exists with user name: " + booking.getUserId());
+
+ Notification sentNotification = sendNotification(booking, user);
+ booking.setNotificationId(sentNotification.getId());
+ booking.setUpdatedOn(LocalDateTime.now());
+ this.bookingRepository.save(booking);
+ this.LOGGER.info("bookSeats() Notification sent , also updated the notification id to booking");
+
+ return makeReturnedData(booking, user);
+
+ }
+
+ }
+
+ private JSONObject makeReturnedData(Booking booking, User user) {
+ JSONObject result = new JSONObject();
+ /**
+ * user details:
+ */
+ JSONObject userDetails = new JSONObject();
+ userDetails.put("bookedBy", user.getFirstName() + " " + user.getLastName());
+ result.put("userDtails", userDetails);
+
+ JSONObject movieDetails = new JSONObject();
+ Optional movie = this.movieRepo.findById(booking.getMovieId());
+ Movie movieFromDb = movie.get();
+ if (movieFromDb == null)
+ throw new DummyBookMyShowException("There is no movie found with id " + booking.getMovieId());
+ movieDetails.put("movieName", movieFromDb.getName());
+ result.put("movieDetails", movieDetails);
+
+ JSONObject theaterDetails = new JSONObject();
+ Optional theater = this.theaterRepo.findById(booking.getTheaterId());
+ Theater theaterFromDb = theater.get();
+ if (theaterFromDb == null)
+ throw new DummyBookMyShowException("There is no theater found with id " + booking.getTheaterId());
+ theaterDetails.put("theaterName", theaterFromDb.getName());
+ theaterDetails.put("theaterAddress", theaterFromDb.getAddress());
+ result.put("theaterDetails", theaterDetails);
+
+ JSONObject ticketDetails = new JSONObject();
+ ticketDetails.put("ticketNumbers", booking.getSeatNumbers());
+ ticketDetails.put("totalPrice", booking.getTotalPrice());
+ result.put("ticketDetails", ticketDetails);
+
+ return result;
+
+ }
+
+ private Payment doPayment(Booking booking) {
+ Payment dummyPayment = new Payment();
+ dummyPayment.setBookingId(booking.getBookingId());
+ dummyPayment.setAmount(booking.getTotalPrice());
+ dummyPayment.setStatus(Status.SUCCESS);
+ dummyPayment.setCreatedOn(LocalDateTime.now());
+ dummyPayment.setMethod(PaymentMethod.CREDITCARD);
+ dummyPayment.setSourceDetails("HDFC CC NO: 123456789123");
+ /**
+ * TODO : if payment is not success then un-book the seats
+ */
+
+ Payment paymentFromDb = this.paymentRepository.save(dummyPayment);
+ this.LOGGER.info("bookSeats() saved dummy payment ...");
+ return paymentFromDb;
+ }
+
+ private Notification sendNotification(Booking booking, User user) {
+ Notification tobeSendNotification = new Notification();
+ tobeSendNotification.setBookingId(booking.getBookingId());
+ tobeSendNotification.setStatus(Status.SUCCESS);
+ tobeSendNotification.setReceiverEmail(user.getEmail());
+ tobeSendNotification.setReceiverMobileNo(user.getMobileNumber());
+ tobeSendNotification.setReceiverType(NotificationType.EMAIL);
+ tobeSendNotification.setSenderEmail(DO_NOT_REPLY_DUMMY_BMS_COM);
+ setTinyUrl(tobeSendNotification, booking, booking.getUserId());
+ tobeSendNotification.setCreatedOn(LocalDateTime.now());
+ tobeSendNotification.setSendTime(LocalDateTime.now());
+ Notification sentNotification = this.notificationRepo.save(tobeSendNotification);
+ return sentNotification;
+ }
+
+ private void setTinyUrl(Notification tobeSendNotification, Booking booking, String userName) {
+ String bookingurl = "https://bms.com/?bookingid = 2&username =" + userName + "&totalAmount="
+ + booking.getTotalPrice() + "&totalSeatBoooked=" + booking.getSeatBooked();
+ Url url = new Url();
+ url.setCreatedOn(LocalDateTime.now());
+ url.setOriginalUrl(bookingurl);
+ String shorturl = this.urlService.convertToShortUrl(url);
+ tobeSendNotification.setTinyUrl(shorturl);
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/service/impl/UrlServiceImpl.java b/src/main/java/com/dummy/bookmyshow/service/impl/UrlServiceImpl.java
new file mode 100644
index 0000000..4526f54
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/service/impl/UrlServiceImpl.java
@@ -0,0 +1,89 @@
+package com.dummy.bookmyshow.service.impl;
+
+import java.time.LocalDateTime;
+import java.util.Optional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.dummy.bookmyshow.entity.Url;
+import com.dummy.bookmyshow.repository.UrlRepository;
+import com.dummy.bookmyshow.util.DummyBookMyShowException;
+
+@Service
+public class UrlServiceImpl {
+
+ private String allowedCharString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ private char[] allowedChars = allowedCharString.toCharArray();
+
+ @Autowired
+ private UrlRepository urlRepository;
+
+ /**
+ * Idea is to store the longUrl to DB and get the id from the db for this entry
+ * Now that id will be integer, So convert that id to base 64 based on allowed
+ * chars return the converted string
+ *
+ * @param url
+ * @return
+ */
+ public String convertToShortUrl(Url url) {
+ // first save the long url to db
+ url.setCreatedOn(LocalDateTime.now());
+ Url savedUrl = this.urlRepository.save(url);
+ long storedLongUrlid = savedUrl.getId();
+ return convertToShortUrl(storedLongUrlid);
+ }
+
+ /**
+ * get the base 64 string from this id and return that
+ *
+ * @param id
+ * @return
+ */
+ private String convertToShortUrl(long id) {
+ StringBuilder sb = new StringBuilder();
+ int base = allowedChars.length;
+ if (id == 0) {
+ return String.valueOf(allowedChars[0]);
+
+ }
+ while (id > 0) {
+ sb.append(allowedChars[(int) id % base]);
+ id = id / base;
+ }
+ return sb.reverse().toString();
+
+ }
+
+ /**
+ * Now first get the decimal from this string , base 64 to decimal The get the
+ * original url from DB
+ *
+ * @param shortUrl
+ * @return
+ */
+ public String getOriginalUrl(String shortUrl) {
+ long id = convertBase64ToDecimal(shortUrl);
+ Optional url = this.urlRepository.findById(id);
+ Url urlFromDb = url.get();
+ if (urlFromDb == null) {
+ throw new DummyBookMyShowException("No id exists DB for this ID");
+
+ }
+ return urlFromDb.getOriginalUrl();
+ }
+
+ private long convertBase64ToDecimal(String shortUrl) {
+ int base = allowedChars.length;
+ int pow = 0;
+ int start = shortUrl.length() - 1;
+ long decimal = 0;
+ while (start >= 0) {
+ decimal += allowedCharString.indexOf(shortUrl.charAt(start)) * Math.pow(base, pow++);
+ start--;
+ }
+ return decimal;
+ }
+
+}
diff --git a/src/main/java/com/dummy/bookmyshow/util/DummyBookMyShowException.java b/src/main/java/com/dummy/bookmyshow/util/DummyBookMyShowException.java
new file mode 100644
index 0000000..6427d21
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/util/DummyBookMyShowException.java
@@ -0,0 +1,10 @@
+package com.dummy.bookmyshow.util;
+
+public class DummyBookMyShowException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ public DummyBookMyShowException(String errorMsg) {
+ super(errorMsg);
+ }
+}
diff --git a/src/main/java/com/dummy/bookmyshow/util/ResponseParser.java b/src/main/java/com/dummy/bookmyshow/util/ResponseParser.java
new file mode 100644
index 0000000..a13e613
--- /dev/null
+++ b/src/main/java/com/dummy/bookmyshow/util/ResponseParser.java
@@ -0,0 +1,66 @@
+package com.dummy.bookmyshow.util;
+
+import java.io.Serializable;
+
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ * @author sramveer
+ * This class will parse the rest response to custom response JSON
+ *
+ */
+
+@Component
+public class ResponseParser implements Serializable {
+
+ /**
+ * serialVersionUID
+ */
+ private static final long serialVersionUID = 1L;
+ private int statusCode;
+ private String developerMessage;
+ private String userMessage;
+ /**
+ * Method to build custom response
+ * @param statusCode
+ * @param developerMessage
+ * @param userMessage
+ * @return
+ */
+ public ResponseParser build(int statusCode, String developerMessage, String userMessage) {
+ this.statusCode = statusCode;
+ this.developerMessage = developerMessage;
+ this.userMessage = userMessage;
+ return this;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ public String getDeveloperMessage() {
+ return developerMessage;
+ }
+
+ public void setDeveloperMessage(String developerMessage) {
+ this.developerMessage = developerMessage;
+ }
+
+ public String getUserMessage() {
+ return userMessage;
+ }
+
+ public void setUserMessage(String userMessage) {
+ this.userMessage = userMessage;
+ }
+ @Override
+ public String toString() {
+ return "ResponseHelper [statusCode=" + statusCode + ", developerMessage=" + developerMessage + ", userMessage="
+ + userMessage + "]";
+ }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000..97f379e
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,30 @@
+#server.port=8090
+
+
+## MYSQL config
+#spring.datasource.url=jdbc:mysql://localhost:3306/bookmyshow
+#spring.datasource.username=bookmyshow
+#spring.datasource.password=bookmyshow
+
+
+# The SQL dialect makes Hibernate generate better SQL for the chosen database
+spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
+
+# Hibernate ddl auto (create, create-drop, validate, update)
+spring.jpa.hibernate.ddl-auto =update
+#to show the sql in console
+spring.jpa.show-sql=true
+spring.jpa.properties.hibernate.format_sql=true
+
+
+#new postgres
+##spring.datasource.url=jdbc:mysql://35.221.65.154:3306/bookmyshow
+spring.datasource.url=jdbc:mysql:///bookmyshow?cloudSqlInstance=dummybms:asia-northeast1:dummysqlv2&socketFactory=com.google.cloud.sql.mysql.SocketFactory&user=root&password=
+spring.datasource.username=root
+spring.datasource.password=
+
+
+#dummybms:asia-northeast1:dummybmssql
+
+
+#spring.datasource.url=jdbc:postgresql:///covid?cloudSqlInstance=corona-19-india:asia-northeast1:newpostgres&socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=covid&password=covid
diff --git a/src/main/resources/config.sql b/src/main/resources/config.sql
new file mode 100644
index 0000000..d25d65f
--- /dev/null
+++ b/src/main/resources/config.sql
@@ -0,0 +1,6 @@
+CREATE DATABASE bookmyshow;
+CREATE USER 'bookmyshow'@'localhost' IDENTIFIED BY 'bookmyshow';
+GRANT ALL PRIVILEGES ON bookmyshow.* TO 'bookmyshow'@'localhost';
+commit;
+
+ALTER DATABASE bookmyshow CHARACTER SET utf8 COLLATE utf8_general_ci;
diff --git a/src/test/java/com/dummy/bookmyshow/BookmyshowApplicationTests.java b/src/test/java/com/dummy/bookmyshow/BookmyshowApplicationTests.java
new file mode 100644
index 0000000..d650e83
--- /dev/null
+++ b/src/test/java/com/dummy/bookmyshow/BookmyshowApplicationTests.java
@@ -0,0 +1,13 @@
+package com.dummy.bookmyshow;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class BookmyshowApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}