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() { + } + +}