diff --git a/.idea/encodings.xml b/.idea/encodings.xml
index aa00ffa..35756ee 100644
--- a/.idea/encodings.xml
+++ b/.idea/encodings.xml
@@ -2,6 +2,6 @@
-
+
\ No newline at end of file
diff --git a/LinkedInClient/.gitignore b/LinkedInClient/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/LinkedInClient/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/LinkedInClient/.idea/.gitignore b/LinkedInClient/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/LinkedInClient/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/LinkedInClient/.idea/encodings.xml b/LinkedInClient/.idea/encodings.xml
new file mode 100644
index 0000000..aa00ffa
--- /dev/null
+++ b/LinkedInClient/.idea/encodings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LinkedInClient/.idea/misc.xml b/LinkedInClient/.idea/misc.xml
new file mode 100644
index 0000000..5d6b03c
--- /dev/null
+++ b/LinkedInClient/.idea/misc.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LinkedInClient/.idea/uiDesigner.xml b/LinkedInClient/.idea/uiDesigner.xml
new file mode 100644
index 0000000..2b63946
--- /dev/null
+++ b/LinkedInClient/.idea/uiDesigner.xml
@@ -0,0 +1,124 @@
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/LinkedInClient/.idea/vcs.xml b/LinkedInClient/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/LinkedInClient/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LinkedInClient/.mvn/wrapper/maven-wrapper.jar b/LinkedInClient/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000..c1dd12f
Binary files /dev/null and b/LinkedInClient/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/LinkedInClient/.mvn/wrapper/maven-wrapper.properties b/LinkedInClient/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000..40ca015
--- /dev/null
+++ b/LinkedInClient/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
\ No newline at end of file
diff --git a/LinkedInClient/mvnw b/LinkedInClient/mvnw
new file mode 100644
index 0000000..8a8fb22
--- /dev/null
+++ b/LinkedInClient/mvnw
@@ -0,0 +1,316 @@
+#!/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 /usr/local/etc/mavenrc ] ; then
+ . /usr/local/etc/mavenrc
+ fi
+
+ 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="`\\unset -f command; \\command -v 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/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.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" || rm -f "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$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 \
+ $MAVEN_DEBUG_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" \
+ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/LinkedInClient/mvnw.cmd b/LinkedInClient/mvnw.cmd
new file mode 100644
index 0000000..1d8ab01
--- /dev/null
+++ b/LinkedInClient/mvnw.cmd
@@ -0,0 +1,188 @@
+@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 "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
+if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\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/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
+
+FOR /F "usebackq 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%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.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 "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
+if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\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%
+
+cmd /C exit /B %ERROR_CODE%
diff --git a/LinkedInClient/pom.xml b/LinkedInClient/pom.xml
new file mode 100644
index 0000000..aeca305
--- /dev/null
+++ b/LinkedInClient/pom.xml
@@ -0,0 +1,114 @@
+
+
+ 4.0.0
+
+ org.example
+ LinkedInClient
+ 1.0-SNAPSHOT
+ LinkedInClient
+
+
+ UTF-8
+5.10.0
+
+
+
+ mysql
+ mysql-connector-java
+ 8.0.27
+
+
+ org.eclipse.jetty
+ jetty-util-ajax
+ 9.4.46.v20220331
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.17.1
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ 2.17.1
+
+
+ org.openjfx
+ javafx-controls
+ 17.0.6
+
+
+ org.openjfx
+ javafx-fxml
+ 17.0.6
+
+
+ org.kordamp.ikonli
+ ikonli-javafx
+ 12.3.1
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ ${junit.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ ${junit.version}
+ test
+
+
+ de.jensd
+ fontawesomefx-fontawesome
+ 4.7.0-9.1.2
+
+
+ org.json
+ json
+ 20140107
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.15.0
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.11.0
+
+ 17
+ 17
+
+
+
+ org.openjfx
+ javafx-maven-plugin
+ 0.0.8
+
+
+
+ default-cli
+
+ org.example.linkedinclient/org.example.linkedinclient.HelloApplication
+ app
+ app
+ app
+ true
+ true
+ true
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LinkedInClient/src/main/java/module-info.java b/LinkedInClient/src/main/java/module-info.java
new file mode 100644
index 0000000..b7f8b32
--- /dev/null
+++ b/LinkedInClient/src/main/java/module-info.java
@@ -0,0 +1,13 @@
+module org.example.linkedinclient {
+ requires javafx.controls;
+ requires javafx.fxml;
+
+ requires org.kordamp.ikonli.javafx;
+ requires com.fasterxml.jackson.databind;
+ requires json;
+ requires org.eclipse.jetty.util;
+ requires de.jensd.fx.glyphs.fontawesome;
+
+ opens org.example.linkedinclient to javafx.fxml;
+ exports org.example.linkedinclient;
+}
\ No newline at end of file
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/Bio.java b/LinkedInClient/src/main/java/org/example/linkedinclient/Bio.java
new file mode 100644
index 0000000..feb6a38
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/Bio.java
@@ -0,0 +1,50 @@
+package org.example.linkedinclient;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Bio {
+ @JsonProperty("userId")
+ private String userId;
+ @JsonProperty("bioText")
+ private String bioText;
+
+ @JsonProperty("location")
+ private String location;
+
+
+ public Bio(String userId, String bioText, String location) {
+ this.userId = userId;
+ this.bioText = bioText;
+ this.location = location;
+ }
+
+ public Bio() {
+
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public String getBioText() {
+ return bioText;
+ }
+
+ public void setBioText(String bioText) {
+ this.bioText = bioText;
+ }
+
+ public String getLocation() {
+ return location;
+ }
+
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+}
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/Comment.java b/LinkedInClient/src/main/java/org/example/linkedinclient/Comment.java
new file mode 100644
index 0000000..fa698ce
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/Comment.java
@@ -0,0 +1,20 @@
+package org.example.linkedinclient;
+
+public class Comment extends Content {
+ private String parentId;
+
+ public Comment(String posterId, String content, String parentId) {
+ super(posterId, content);
+ this.parentId = parentId;
+ }
+
+ public Comment() {}
+
+ public String getParentId() {
+ return parentId;
+ }
+
+ public void setParentId(String parentId) {
+ this.parentId = parentId;
+ }
+}
\ No newline at end of file
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/CommentController.java b/LinkedInClient/src/main/java/org/example/linkedinclient/CommentController.java
new file mode 100644
index 0000000..bbaf422
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/CommentController.java
@@ -0,0 +1,743 @@
+package org.example.linkedinclient;
+
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon;
+import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView;
+import javafx.fxml.FXML;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.ScrollPane;
+import javafx.scene.control.TextArea;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
+import javafx.scene.shape.Circle;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.*;
+import java.net.ConnectException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.example.linkedinclient.HelloApplication.LoggedInUser;
+
+public class CommentController {
+
+
+ @FXML
+ private Button EventBtn;
+
+ @FXML
+ private Button articleBtn;
+
+ @FXML
+ private FontAwesomeIconView closeBtn;
+
+ @FXML
+ private Label commentCountLabel;
+
+ @FXML
+ private VBox commentsBox;
+
+ @FXML
+ private Button followButton;
+
+ @FXML
+ private Button likeButton;
+
+ @FXML
+ private Button mediaBtn;
+
+ @FXML
+ private VBox postBox;
+
+ @FXML
+ private Button postButton;
+
+ @FXML
+ private Label postContentLabel;
+
+ @FXML
+ private VBox postCreationVBox;
+
+ @FXML
+ private Label postHeaderLabel;
+
+ @FXML
+ private TextArea postTextArea;
+
+ @FXML
+ private Button shareButton;
+
+ @FXML
+ private Label timelineLabel;
+ @FXML
+ private Label posterIdLabel;
+ @FXML
+ private ImageView profPostImgView;
+ static Post post;
+ private Map followButtonsMap = new HashMap<>();
+ private Map likeButtonsMap = new HashMap<>();
+ private int commentCounts;
+
+ @FXML
+ void OnMouseClickedArticleBtn(MouseEvent event) {
+
+ }
+
+ @FXML
+ void OnMouseClickedCloseBtn(MouseEvent event) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ postTextArea.setText("");
+ helloApplication.changeScene(3);
+ }
+
+ @FXML
+ void OnMouseClickedMediaBtn(MouseEvent event) {
+
+ }
+
+ @FXML
+ void OnMouseClickedPostBtn(MouseEvent event) throws IOException {
+ String userId = LoggedInUser.getId();
+ Comment comment = new Comment(userId, postTextArea.getText(), post.getPostId());
+ String res = saveComment(comment);
+ comment.setPostId(res);
+ addComment(comment , downloadProfCommentImg(comment.getPosterId()));
+ }
+
+ private String saveComment(Comment comment) throws IOException {
+ try {
+ String response;
+ URL url = new URL("http://localhost:8000/comments/" + LoggedInUser.getId() + "/" + post.getPostId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ String json = objectMapper.writeValueAsString(comment);
+
+ byte[] postDataBytes = json.getBytes();
+
+ con.setRequestMethod("POST");
+ con.setDoOutput(true);
+ con.getOutputStream().write(postDataBytes);
+
+ Reader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ StringBuilder sb = new StringBuilder();
+ for (int c; (c = in.read()) > 0; )
+ sb.append((char) c);
+ response = sb.toString();
+ return response;
+ }
+ catch (ConnectException e) {
+ return "Connection failed";
+ }
+ }
+
+
+ @FXML
+ void onMouseClickedTextArea(MouseEvent event) {
+ postButton.setVisible(true);
+ }
+
+ public void initialize() throws IOException {
+ profPostImgView.setImage(new Image(downloadProfPostImg()));
+ posterIdLabel.setText(" " + post.getPosterId());
+ postContentLabel.setText(post.getContent());
+ if (isFollowing(LoggedInUser.getId(), post.getPosterId())) {
+ followButton.setText("followed");
+ followButton.setOnMouseEntered(event -> followButton.setStyle("-fx-background-color: green; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followButton.setOnMouseExited(event -> followButton.setStyle("-fx-background-color: green; -fx-text-fill: white;"));
+ FontAwesomeIconView followIcon = new FontAwesomeIconView(FontAwesomeIcon.CHECK);
+ followIcon.getStyleClass().add("followIcon");
+ followButton.setGraphic(followIcon);
+ followButton.setStyle("-fx-background-color: green; -fx-text-fill: white;");
+ }
+ if (IsLike(LoggedInUser.getId(), post.getPostId())) {
+ likeButton.setText(Integer.toString(post.getLikesNumber()));
+ likeButton.setStyle("-fx-background-color: #ccc;");
+ }
+ URL url = new URL("http://localhost:8000/comments/" + post.getPostId());
+ String response;
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] comments = toStringArray(jsonObject);
+ commentCounts = 0;
+ for (String t : comments) {
+ JSONObject obj = new JSONObject(t);
+ Comment comment = new Comment(obj.getString("posterId"), obj.getString("content"), post.getPostId());
+ comment.setPostId(obj.getString("postId"));
+ comment.setLikesNumber(obj.getInt("likesNumber"));
+ comment.setCommentsNumber(obj.getInt("commentsNumber"));
+ comment.setTimeStamp(new Date(obj.getLong("timeStamp")));
+ addComment(comment , downloadProfCommentImg(comment.getPosterId()));
+ if (IsLike(LoggedInUser.getId(), comment.getPostId())) {
+ Button likeButton = likeButtonsMap.get(comment.getPostId());
+ likeButton.setText(Integer.toString(comment.getLikesNumber()));
+ likeButton.setStyle("-fx-background-color: #ccc;");
+ }
+ if (isFollowing(LoggedInUser.getId(), comment.getPosterId())) {
+ Button followBtn = followButtonsMap.get(comment.getPostId());
+ followBtn.setText("followed");
+ followBtn.setOnMouseEntered(event -> followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followBtn.setOnMouseExited(event -> followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white;"));
+ FontAwesomeIconView followIcon = new FontAwesomeIconView(FontAwesomeIcon.CHECK);
+ followIcon.getStyleClass().add("followIcon");
+ followBtn.setGraphic(followIcon);
+ followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white;");
+ }
+ }
+ commentCountLabel.setText(commentCounts + " Comments");
+
+
+ }
+ private String downloadProfCommentImg(String userId) {
+ if (fileExists("C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\profPic" + userId + ".png"))
+ return "C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\profPic" + userId + ".png";
+ return "C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\logo.png";
+ }
+ private String downloadProfPostImg() {
+ if (fileExists("C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\profPic" + post.getPosterId() + ".png"))
+ return "C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\profPic" + post.getPosterId() + ".png";
+ return "C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\logo.png";
+ }
+ public static boolean fileExists(String filePath) {
+ File file = new File(filePath);
+ return file.exists() && file.isFile();
+ }
+ private void updateCommentCount() {
+ commentCountLabel.setText(++commentCounts + " Comments");
+ }
+
+ private void addComment(Comment comment, String profileImagePath) {
+ updateCommentCount();
+ VBox commentBox = new VBox(10);
+ commentBox.getStyleClass().add("post-box");
+ commentBox.setPadding(new Insets(10));
+ commentBox.setStyle("-fx-background-color: #ffffff; -fx-border-color: #dddddd; -fx-border-radius: 5; -fx-background-radius: 5;");
+
+// Profile Image
+ Image profileImage = new Image(profileImagePath);
+ ImageView profileImageView = new ImageView(profileImage);
+ profileImageView.setFitWidth(50);
+ profileImageView.setFitHeight(50);
+ Circle clip = new Circle(25, 25, 25);
+ profileImageView.setClip(clip);
+
+ Label commentHeader = new Label(comment.getPosterId());
+ commentHeader.getStyleClass().add("post-header");
+
+// Follow Button
+ Button followBtn = new Button("Follow");
+ FontAwesomeIconView followIcon = new FontAwesomeIconView(FontAwesomeIcon.USER_PLUS);
+ followIcon.getStyleClass().add("followIcon");
+ followBtn.setGraphic(followIcon);
+ followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;");
+ followBtn.setOnMouseEntered(event -> followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followBtn.setOnMouseExited(event -> followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;"));
+ followBtn.setCursor(javafx.scene.Cursor.HAND);
+ followButtonsMap.put(comment.getPostId(), followBtn);
+ followBtn.setOnAction(event -> {
+ try {
+ handleFollow(comment, followBtn);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+// Header with Profile Image, Name, and Follow Button
+ HBox headerBox = new HBox(10, profileImageView, commentHeader, followBtn);
+ headerBox.setAlignment(Pos.CENTER_LEFT);
+ HBox.setHgrow(commentHeader, Priority.ALWAYS);
+
+// Comment Content
+ Label commentLabel = new Label(comment.getContent());
+ commentLabel.setWrapText(true); // Ensure text wraps within the label
+
+ ScrollPane scrollPane = new ScrollPane();
+ scrollPane.setContent(commentLabel);
+ scrollPane.setFitToWidth(true);
+ scrollPane.setPrefHeight(100);
+ scrollPane.getStyleClass().add("scroll-pane-label");
+
+// Timeline
+ Label timelineLabel = new Label("Posted on: " + comment.getTimeStamp());
+ timelineLabel.getStyleClass().add("timeline-label");
+
+// Action Buttons
+ HBox commentActions = new HBox(10);
+ commentActions.setAlignment(Pos.CENTER);
+
+ Button likeButton = new Button("Like");
+ FontAwesomeIconView thumb = new FontAwesomeIconView(FontAwesomeIcon.THUMBS_UP);
+ thumb.getStyleClass().add("thumbIcon");
+ likeButton.setGraphic(thumb);
+ likeButton.setCursor(javafx.scene.Cursor.HAND);
+ likeButton.getStyleClass().addAll("post-box-btn", "likeBtn");
+ likeButtonsMap.put(comment.getPostId(), likeButton);
+ likeButton.setOnAction(event -> {
+ handleLike(comment, likeButton);
+ });
+
+ Button shareButton = new Button("Share");
+ FontAwesomeIconView share = new FontAwesomeIconView(FontAwesomeIcon.SHARE);
+ share.getStyleClass().add("shareIcon");
+ shareButton.setGraphic(share);
+ shareButton.setCursor(javafx.scene.Cursor.HAND);
+ shareButton.getStyleClass().addAll("post-box-btn", "shareBtn");
+
+// Add action listeners using lambdas
+ likeButton.setOnAction(event -> handleLike(comment, likeButton));
+ shareButton.setOnAction(event -> handleShare(post));
+
+ commentActions.getChildren().addAll(likeButton, shareButton);
+
+ VBox commentContentBox = new VBox(5, headerBox, scrollPane, timelineLabel, commentActions);
+ commentBox.getChildren().add(commentContentBox);
+
+// Add commentBox to commentsBox at the appropriate index
+ commentsBox.getChildren().add(0, commentBox);
+
+ }
+
+ public void OnMouseClickedLikeBtn(MouseEvent mouseEvent) {
+ try {
+ if (!IsLike(LoggedInUser.getId(), post.getPostId())) {
+ URL url = new URL("http://localhost:8000/likes/" + LoggedInUser.getId() + "/" + post.getPostId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("POST");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful")) {
+ post.addLike();
+ likeButton.setText(Integer.toString(post.getLikesNumber()));
+ likeButton.setStyle("-fx-background-color: #ccc;");
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ else {
+ URL url = new URL("http://localhost:8000/likes/" + LoggedInUser.getId() + "/" + post.getPostId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("DELETE");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful")) {
+ post.takeLike();
+ likeButton.setText(Integer.toString(post.getLikesNumber()));
+ likeButton.setStyle("-fx-background-color: transparent;");
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public void OnMouseClickedShareBtn(MouseEvent mouseEvent) {
+ }
+
+ public void OnMouseEnteredShareBtn(MouseEvent mouseEvent) {
+ shareButton.setStyle("-fx-background-color: #ccc");
+ }
+
+ public void OnMouseEnteredLikeBtn(MouseEvent mouseEvent) {
+ likeButton.setStyle("-fx-background-color: #ccc");
+ }
+
+ public void OnMouseExitedLikeBtn(MouseEvent mouseEvent) throws IOException {
+ if (!IsLike(LoggedInUser.getId(), post.getPostId()))
+ likeButton.setStyle("-fx-background-color: transparent");
+ }
+
+ public void OnMouseExitedShareBtn(MouseEvent mouseEvent) {
+ shareButton.setStyle("-fx-background-color: transparent");
+ }
+
+ public void OnMouseEnteredFollowBtn(MouseEvent mouseEvent) {
+
+ followButton.setStyle("-fx-opacity: 0.7; -fx-background-color: #0598ff; -fx-text-fill: white;");
+ }
+
+ public void OnMouseExitedFollowBtn(MouseEvent mouseEvent) {
+ followButton.setStyle("-fx-opacity: 1; -fx-background-color: #0598ff; -fx-text-fill: white;");
+ }
+
+
+
+ // Example handlers for like, comment, and share actions
+ private void handleLike(Comment comment, Button likeButton) {
+ try {
+ if (!IsLike(LoggedInUser.getId(), comment.getPostId())) {
+ URL url = new URL("http://localhost:8000/likes/" + LoggedInUser.getId() + "/" + comment.getPostId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("POST");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful")) {
+ comment.addLike();
+ likeButton.setText(Integer.toString(comment.getLikesNumber()));
+ likeButton.setStyle("-fx-background-color: #ccc;");
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ else {
+ URL url = new URL("http://localhost:8000/likes/" + LoggedInUser.getId() + "/" + comment.getPostId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("DELETE");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful")) {
+ comment.takeLike();
+ likeButton.setText(Integer.toString(comment.getLikesNumber()));
+ likeButton.setStyle("-fx-background-color: transparent;");
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ public boolean IsLike(String userId, String postId) throws IOException {
+ ArrayList likes = getAllLikes();
+ for (Like l: likes) {
+ if (l.getLiker().equals(userId) && l.getLiked().equals(postId))
+ return true;
+ }
+ return false;
+ }
+
+ public ArrayList getAllLikes() throws IOException {
+ String response;
+ URL url = new URL("http://localhost:8000/likes");
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] users = toStringArray(jsonObject);
+ ArrayList likes = new ArrayList<>();
+ for (String t: users) {
+ JSONObject obj = new JSONObject(t);
+ Like l = new Like(obj.getString("liker"), obj.getString("liked"));
+ likes.add(l);
+ }
+ return likes;
+ }
+
+ private void handleFollow(Comment comment, Button followBtn) throws IOException {
+ if (!isFollowing(LoggedInUser.getId(), comment.getPosterId())) {
+ URL url = new URL("http://localhost:8000/follows/" + LoggedInUser.getId() + "/" + comment.getPosterId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("POST");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful!")) {
+ followBtn.setText("followed");
+ followBtn.setOnMouseEntered(event -> followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followBtn.setOnMouseExited(event -> followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white;"));
+ FontAwesomeIconView followIcon = new FontAwesomeIconView(FontAwesomeIcon.CHECK);
+ followIcon.getStyleClass().add("followIcon");
+ followBtn.setGraphic(followIcon);
+ followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white;");
+ changeOtherFollowBtns(comment);
+ if (post.getPosterId().equals(comment.getPosterId())) {
+ followButton.setText("followed");
+ followButton.setOnMouseEntered(event -> followButton.setStyle("-fx-background-color: green; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followButton.setOnMouseExited(event -> followButton.setStyle("-fx-background-color: green; -fx-text-fill: white;"));
+ FontAwesomeIconView followPostIcon = new FontAwesomeIconView(FontAwesomeIcon.CHECK);
+ followPostIcon.getStyleClass().add("followIcon");
+ followButton.setGraphic(followIcon);
+ followButton.setStyle("-fx-background-color: green; -fx-text-fill: white;");
+ }
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ else {
+ URL url = new URL("http://localhost:8000/follows/" + LoggedInUser.getId() + "/" + comment.getPosterId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("DELETE");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful!")) {
+ followBtn.setText("follow");
+ FontAwesomeIconView followIcon = new FontAwesomeIconView(FontAwesomeIcon.USER_PLUS);
+ followIcon.getStyleClass().add("followIcon");
+ followBtn.setGraphic(followIcon);
+ followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;");
+ followBtn.setOnMouseEntered(event -> followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followBtn.setOnMouseExited(event -> followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;"));
+ changeOtherFollowBtns(comment);
+ if (post.getPosterId().equals(comment.getPosterId())) {
+ followButton.setText("follow");
+ FontAwesomeIconView followPostIcon = new FontAwesomeIconView(FontAwesomeIcon.USER_PLUS);
+ followPostIcon.getStyleClass().add("followIcon");
+ followButton.setGraphic(followPostIcon);
+ followButton.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;");
+ followButton.setOnMouseEntered(event -> followButton.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followButton.setOnMouseExited(event -> followButton.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;"));
+ }
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+
+ }
+ private void changeOtherFollowBtns(Comment comment) throws IOException {
+ String response;
+ URL url = new URL("http://localhost:8000/comments/" + post.getPostId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] posts1 = toStringArray(jsonObject);
+ for (String t : posts1) {
+ JSONObject obj = new JSONObject(t);
+ if (comment.getPosterId().equals(obj.getString("posterId"))) {
+ System.out.println(obj.getString("postId"));
+ Button followBtn = followButtonsMap.get(obj.getString("postId"));
+ if (isFollowing(LoggedInUser.getId(), comment.getPosterId())) {
+ followBtn.setText("followed");
+ followBtn.setOnMouseEntered(event -> followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followBtn.setOnMouseExited(event -> followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white;"));
+ FontAwesomeIconView followIcon = new FontAwesomeIconView(FontAwesomeIcon.CHECK);
+ followIcon.getStyleClass().add("followIcon");
+ followBtn.setGraphic(followIcon);
+ followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white;");
+ }
+ else {
+ followBtn.setText("follow");
+ FontAwesomeIconView followIcon = new FontAwesomeIconView(FontAwesomeIcon.USER_PLUS);
+ followIcon.getStyleClass().add("followIcon");
+ followBtn.setGraphic(followIcon);
+ followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;");
+ followBtn.setOnMouseEntered(event -> followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followBtn.setOnMouseExited(event -> followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;"));
+ }
+ }
+ }
+ }
+ private ArrayList getAllFollowings(String userId) throws IOException {
+ String response;
+ URL url = new URL("http://localhost:8000/follows/followings/" + userId);
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] follows = toStringArray(jsonObject);
+ ArrayList followings = new ArrayList<>();
+ for (String t: follows) {
+ JSONObject obj = new JSONObject(t);
+ Follow l = new Follow(obj.getString("follower"), obj.getString("followed"));
+ followings.add(l);
+ }
+ return followings;
+ }
+ private boolean isFollowing(String follower, String followed) throws IOException {
+ ArrayList followings = getAllFollowings(follower);
+ for (Follow t: followings) {
+ if (t.getFollowed().equals(followed) && t.getFollower().equals(follower))
+ return true;
+ }
+ return false;
+ }
+
+ private void handleComment(Post post) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ postTextArea.setText("");
+ CommentController.post = post;
+ helloApplication.changeScene(4);
+ }
+
+ private void handleShare(Post post) {
+ // Handle share action
+ System.out.println("Post shared: " + post.getPostId());
+ }
+
+ public static String[] toStringArray(JSONArray array) {
+ if(array == null)
+ return new String[0];
+
+ String[] arr = new String[array.length()];
+ for(int i = 0; i < arr.length; i++)
+ arr[i] = array.optString(i);
+ return arr;
+ }
+
+ public void OnMouseClickedPostFollowBtn(MouseEvent mouseEvent) throws IOException {
+ if (!isFollowing(LoggedInUser.getId(), post.getPosterId())) {
+ URL url = new URL("http://localhost:8000/follows/" + LoggedInUser.getId() + "/" + post.getPosterId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("POST");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful!")) {
+ followButton.setText("followed");
+ followButton.setOnMouseEntered(event -> followButton.setStyle("-fx-background-color: green; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followButton.setOnMouseExited(event -> followButton.setStyle("-fx-background-color: green; -fx-text-fill: white;"));
+ FontAwesomeIconView followIcon = new FontAwesomeIconView(FontAwesomeIcon.CHECK);
+ followIcon.getStyleClass().add("followIcon");
+ followButton.setGraphic(followIcon);
+ followButton.setStyle("-fx-background-color: green; -fx-text-fill: white;");
+ Comment com = new Comment();
+ com.setPosterId(post.getPosterId());
+ changeOtherFollowBtns(com);
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ else {
+ URL url = new URL("http://localhost:8000/follows/" + LoggedInUser.getId() + "/" + post.getPosterId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("DELETE");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful!")) {
+ followButton.setText("follow");
+ FontAwesomeIconView followIcon = new FontAwesomeIconView(FontAwesomeIcon.USER_PLUS);
+ followIcon.getStyleClass().add("followIcon");
+ followButton.setGraphic(followIcon);
+ followButton.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;");
+ followButton.setOnMouseEntered(event -> followButton.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followButton.setOnMouseExited(event -> followButton.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;"));
+ Comment com = new Comment();
+ com.setPosterId(post.getPosterId());
+ changeOtherFollowBtns(com);
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/Content.java b/LinkedInClient/src/main/java/org/example/linkedinclient/Content.java
new file mode 100644
index 0000000..1506739
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/Content.java
@@ -0,0 +1,106 @@
+package org.example.linkedinclient;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.ArrayList;
+import java.util.Date;
+
+public class Content {
+ @JsonProperty("postId")
+ private String postId;
+ @JsonProperty("posterId")
+ private String posterId;
+ @JsonProperty("content")
+ private String content;
+ @JsonProperty("likesNumber")
+ private int likesNumber;
+ @JsonProperty("timeStamp")
+ private Date timeStamp;
+ @JsonProperty("commentsNumber")
+ private int commentsNumber;
+ @JsonProperty("mediaPaths")
+ private ArrayList mediaPaths;
+
+ public Content(String posterId, String content) {
+ this.postId = posterId + System.currentTimeMillis();
+ this.posterId = posterId;
+ this.content = content;
+ this.timeStamp = new Date(System.currentTimeMillis());
+ this.likesNumber = 0;
+ this.commentsNumber = 0;
+ mediaPaths = new ArrayList<>();
+ }
+ public Content() {
+ this.likesNumber = 0;
+ this.commentsNumber = 0;
+ this.timeStamp = new Date(System.currentTimeMillis());
+ mediaPaths = new ArrayList<>();
+ }
+
+ public String getPostId() {
+ return postId;
+ }
+
+ public void setPostId(String postId) {
+ this.postId = postId;
+ }
+
+ public String getPosterId() {
+ return posterId;
+ }
+
+ public void setPosterId(String posterId) {
+ this.posterId = posterId;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ public int getLikesNumber() {
+ return likesNumber;
+ }
+
+ public Date getTimeStamp() {
+ return timeStamp;
+ }
+
+ public void setTimeStamp(Date timeStamp) {
+ this.timeStamp = timeStamp;
+ }
+ public void addLike() {
+ likesNumber++;
+ }
+ public void takeLike() {
+ likesNumber--;
+ }
+
+ public int getCommentsNumber() {
+ return commentsNumber;
+ }
+
+ public void setCommentsNumber(int commentsNumber) {
+ this.commentsNumber = commentsNumber;
+ }
+ public void addCommentsNum() {
+ commentsNumber++;
+ }
+ public void decreaseComment() {
+ commentsNumber--;
+ }
+ public void setLikesNumber(int likesNumber) {
+ this.likesNumber = likesNumber;
+ }
+
+ public ArrayList getMediaPaths() {
+ return mediaPaths;
+ }
+
+ public void setMediaPaths(ArrayList mediaPaths) {
+ this.mediaPaths = mediaPaths;
+ }
+}
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/Education.java b/LinkedInClient/src/main/java/org/example/linkedinclient/Education.java
new file mode 100644
index 0000000..47f642e
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/Education.java
@@ -0,0 +1,106 @@
+package org.example.linkedinclient;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.text.Format;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class Education {
+ @JsonProperty("userId")
+ private String userId;
+ @JsonProperty("institutionName")
+ private String institutionName;
+ @JsonProperty("major")
+ private String major;
+ @JsonProperty("startDate")
+ private Date startDate;
+ @JsonProperty("endDate")
+ private Date endDate;
+ @JsonProperty("grade")
+ private double grade;
+ @JsonProperty("activities")
+ private String activities;
+ @JsonProperty("extraExplanation")
+ private String extraExplanation;
+
+ public Education(String userId, String institutionName, String major, String startDate, String endDate, double grade, String activities, String extraExplanation) throws ParseException {
+ this.userId = userId;
+ this.institutionName = institutionName;
+ this.major = major;
+ this.startDate = new SimpleDateFormat("yyyy-MM-dd").parse(startDate);
+ this.endDate = new SimpleDateFormat("yyyy-MM-dd").parse(endDate);
+ this.grade = grade;
+ this.activities = activities;
+ this.extraExplanation = extraExplanation;
+ }
+ public Education() {}
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public String getInstitutionName() {
+ return institutionName;
+ }
+
+ public void setInstitutionName(String institutionName) {
+ this.institutionName = institutionName;
+ }
+
+ public String getMajor() {
+ return major;
+ }
+
+ public void setMajor(String major) {
+ this.major = major;
+ }
+
+ public String getStartDate() {
+ Format formatter = new SimpleDateFormat("yyyy-MM-dd");
+ return formatter.format(startDate);
+ }
+
+ public void setStartDate(Date startDate) {
+ this.startDate = startDate;
+ }
+
+ public String getEndDate() {
+ Format formatter = new SimpleDateFormat("yyyy-MM-dd");
+ return formatter.format(endDate);
+ }
+
+ public void setEndDate(Date endDate) {
+ this.endDate = endDate;
+ }
+
+ public double getGrade() {
+ return grade;
+ }
+
+ public void setGrade(double grade) {
+ this.grade = grade;
+ }
+
+ public String getActivities() {
+ return activities;
+ }
+
+ public void setActivities(String activities) {
+ this.activities = activities;
+ }
+
+ public String getExtraExplanation() {
+ return extraExplanation;
+ }
+
+ public void setExtraExplanation(String extraExplanation) {
+ this.extraExplanation = extraExplanation;
+ }
+}
+
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/EducationComponentController.java b/LinkedInClient/src/main/java/org/example/linkedinclient/EducationComponentController.java
new file mode 100644
index 0000000..e9dd233
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/EducationComponentController.java
@@ -0,0 +1,97 @@
+package org.example.linkedinclient;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.DatePicker;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextField;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.ConnectException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+import static org.example.linkedinclient.HelloApplication.LoggedInUser;
+
+public class EducationComponentController {
+ @FXML
+ private TextField degreeField;
+
+ @FXML
+ private DatePicker endDatePicker;
+
+ @FXML
+ private TextField fieldOfStudyField;
+
+ @FXML
+ private TextField institutionField;
+
+ @FXML
+ private DatePicker startDatePicker;
+
+ @FXML
+ private Label wrongLable;
+ public void handleCancel(ActionEvent actionEvent) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ clear();
+ helloApplication.changeScene(6);
+ }
+ private void clear() {
+ degreeField.setText("");
+ fieldOfStudyField.setText("");
+ institutionField.setText("");
+ }
+
+ public void handleSave(ActionEvent actionEvent) throws IOException, ParseException {
+ if (degreeField.getText().isEmpty() || fieldOfStudyField.getText().isEmpty() || institutionField.getText().isEmpty() || endDatePicker.getValue() == null || startDatePicker.getValue() == null)
+ wrongLable.setText("PLEASE FILL ALL OF THE FIELDS!");
+ else {
+ try {
+ String response;
+ URL url = new URL("http://localhost:8000/educations/" + LoggedInUser.getId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ LocalDate startDate = startDatePicker.getValue();
+ LocalDate endDate = endDatePicker.getValue();
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ String startDate1 = startDate.format(formatter);
+ String endDate1 = endDate.format(formatter);
+ Education education = new Education(LoggedInUser.getId(), institutionField.getText(),degreeField.getText() + "," + fieldOfStudyField.getText(), startDate1, endDate1, 0, "", "");
+ ObjectMapper objectMapper = new ObjectMapper();
+ String json = objectMapper.writeValueAsString(education);
+
+ byte[] postDataBytes = json.getBytes();
+
+ con.setRequestMethod("POST");
+ con.setDoOutput(true);
+ con.getOutputStream().write(postDataBytes);
+
+ Reader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ StringBuilder sb = new StringBuilder();
+ for (int c; (c = in.read()) > 0; )
+ sb.append((char) c);
+ response = sb.toString();
+ if (response.equals("successful!")) {
+ HelloApplication helloApplication = new HelloApplication();
+ clear();
+ helloApplication.changeScene(6);
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ catch (ConnectException e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+}
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/EducationViewController.java b/LinkedInClient/src/main/java/org/example/linkedinclient/EducationViewController.java
new file mode 100644
index 0000000..70136e8
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/EducationViewController.java
@@ -0,0 +1,153 @@
+package org.example.linkedinclient;
+
+
+import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView;
+import javafx.fxml.FXML;
+import javafx.scene.Cursor;
+import javafx.scene.control.Label;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Region;
+import javafx.scene.layout.VBox;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.ParseException;
+import java.util.ArrayList;
+
+import static org.example.linkedinclient.FeedController.toStringArray;
+import static org.example.linkedinclient.HelloApplication.LoggedInUser;
+
+public class EducationViewController {
+ @FXML
+ private FontAwesomeIconView addEducationBtn;
+
+ @FXML
+ private FontAwesomeIconView closeBtn;
+
+ @FXML
+ private FontAwesomeIconView editEducationBtn;
+
+ @FXML
+ private ImageView educationImgView;
+
+ @FXML
+ private VBox rootVBox;
+
+ @FXML
+ void OnMouseClickedCloseBtn(MouseEvent event) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(5);
+ }
+
+ @FXML
+ void OnMouseClickedIntsLabel(MouseEvent event) {
+
+ }
+
+ @FXML
+ public void initialize() throws IOException, ParseException {
+ ArrayList educations = getEducations();
+ for (Education education : educations) {
+ addEducation(education.getInstitutionName(), education.getMajor(), education.getStartDate());
+ }
+ }
+
+ private ArrayList getEducations() throws IOException, ParseException {
+ URL url = new URL("http://localhost:8000/educations/" + LoggedInUser.getId());
+ String response;
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] educations = toStringArray(jsonObject);
+ ArrayList educations1 = new ArrayList<>();
+ for (String t : educations) {
+ JSONObject obj = new JSONObject(t);
+ Education education = new Education(LoggedInUser.getId(), obj.getString("institutionName"), obj.getString("major"), obj.getString("startDate"), obj.getString("endDate"), 0, "", "");
+ educations1.add(education);
+ }
+ return educations1;
+ }
+
+
+ private void addEducation(String institution, String major, String date) throws IOException {
+ HBox newEducationBox = createEducationBox(institution, major, date);
+ rootVBox.getChildren().add(1, newEducationBox);
+ }
+
+ private HBox createEducationBox(String institution, String major, String date) {
+ // Creating a new HBox
+ HBox educationBox = new HBox();
+ educationBox.setAlignment(javafx.geometry.Pos.CENTER);
+ educationBox.setStyle("-fx-background-color: #f0f2f0;");
+
+ // Creating the ImageView
+ ImageView imageView = new ImageView(new Image("C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\img\\logo.png"));
+ imageView.setFitHeight(98);
+ imageView.setFitWidth(69);
+ imageView.setPickOnBounds(true);
+ imageView.setPreserveRatio(true);
+
+ // Creating the VBox for labels
+ VBox labelsVBox = new VBox();
+ labelsVBox.setStyle("-fx-background-color: transparent; -fx-border-width: 0 0 0 0;");
+
+ // Institution label
+ Label institutionLabel = new Label(institution);
+ institutionLabel.setCursor(Cursor.HAND);
+ institutionLabel.setFont(new javafx.scene.text.Font("Arial Bold", 18));
+
+ // Major label
+ Label majorLabel = new Label(major);
+ majorLabel.setFont(new javafx.scene.text.Font("Arial", 14));
+
+ // Date label
+ Label dateLabel = new Label(date);
+ dateLabel.setTextFill(javafx.scene.paint.Color.web("#929292"));
+ dateLabel.setFont(new javafx.scene.text.Font("Arial", 14));
+
+ labelsVBox.getChildren().addAll(institutionLabel, majorLabel, dateLabel);
+
+ // Creating the Region for spacing
+ Region region = new Region();
+ region.setPrefHeight(Region.USE_COMPUTED_SIZE);
+ region.setPrefWidth(Region.USE_COMPUTED_SIZE);
+ HBox.setHgrow(region, javafx.scene.layout.Priority.ALWAYS);
+
+ // Creating the edit icon
+ FontAwesomeIconView editIcon = new FontAwesomeIconView();
+ editIcon.setGlyphName("PENCIL");
+ editIcon.setSize("20");
+ editIcon.setCursor(Cursor.HAND);
+
+ // Adding children to the HBox
+ educationBox.getChildren().addAll(imageView, labelsVBox, region, editIcon);
+ return educationBox;
+ }
+
+
+ public void OnMouseClickedAddEduBtn(MouseEvent mouseEvent) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(7);
+ }
+
+ public void OnMouseClickedEditEduBtn(MouseEvent mouseEvent) {
+ }
+}
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/FeedController.java b/LinkedInClient/src/main/java/org/example/linkedinclient/FeedController.java
new file mode 100644
index 0000000..aba9b3f
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/FeedController.java
@@ -0,0 +1,616 @@
+package org.example.linkedinclient;
+
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon;
+import javafx.application.Platform;
+import javafx.concurrent.Task;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.geometry.Insets;
+import javafx.geometry.Pos;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.ScrollPane;
+import javafx.scene.control.TextArea;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.StackPane;
+import javafx.scene.layout.VBox;
+import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView;
+import javafx.scene.shape.Circle;
+import javafx.stage.FileChooser;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.kordamp.ikonli.javafx.FontIcon;
+
+import java.io.*;
+import java.net.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+import static org.example.linkedinclient.HelloApplication.LoggedInUser;
+
+public class FeedController {
+
+ @FXML
+ private Button EventBtn;
+
+ @FXML
+ private Button articleBtn;
+
+ @FXML
+ private VBox feedVBox;
+
+ @FXML
+ private Button jobsBtn;
+
+ @FXML
+ private Button meBtn;
+
+ @FXML
+ private Button mediaBtn;
+
+ @FXML
+ private Button msgBtn;
+
+ @FXML
+ private Button networkBtn;
+
+ @FXML
+ private Button notifBtn;
+
+ @FXML
+ private Button postButton;
+
+ @FXML
+ private VBox postCreationVBox;
+
+ @FXML
+ private Label userNameLabel;
+
+ @FXML
+ private TextArea postTextArea;
+ @FXML
+ private ImageView profileImgView;
+ List pictures = new ArrayList<>();
+ private Map likeButtonsMap = new HashMap<>();
+ private Map followButtonsMap = new HashMap<>();
+
+
+
+ @FXML
+ void OnMouseClickedArticleBtn(MouseEvent event) {
+
+ }
+
+ @FXML
+ void OnMouseClickedPostBtn(MouseEvent event) throws IOException {
+ String userId = LoggedInUser.getId();
+ Post post = new Post(userId, postTextArea.getText());
+ if (!(pictures.isEmpty()) ) {
+ for (int i = 0; i < pictures.size(); i++)
+ post.getMediaPaths().add("a");
+ }
+
+ String res = savePost(post);
+ post.setPostId(res);
+
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
+ String formattedDateTime = simpleDateFormat.format(new Date(System.currentTimeMillis()));
+ if (!pictures.isEmpty())
+ savePicture(post.getPostId());
+ addPostToFeed(post ,post.getContent(), formattedDateTime, downloadProfPostImg(post.getPosterId()));
+ postTextArea.setText("");
+ mediaBtn.setText("Media");
+
+ }
+ public void savePicture(String postId) throws IOException {
+ copyFileToDirectory(pictures.get(0), "C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets", "postPic" + postId + ".png");
+ }
+
+
+
+ @FXML
+ void OnMouseClickedMediaBtn(MouseEvent event) {
+ FileChooser fc = new FileChooser();
+ fc.getExtensionFilters().add(new FileChooser.ExtensionFilter("pictures", "*.png"));
+ List f = fc.showOpenMultipleDialog(null);
+ String res = "";
+ if (f == null)
+ return;
+ for (int i = 0; i < f.size(); i++) {
+ File file = f.get(i);
+ res += file.getName();
+
+ if (i != f.size() - 1)
+ res += ", ";
+ }
+ pictures = f;
+ mediaBtn.setText(res);
+ }
+ private void copyFileToDirectory(File file, String targetDirectory, String newName) throws IOException {
+ Path targetPath = Path.of(targetDirectory, newName);
+ Files.copy(file.toPath(), targetPath, StandardCopyOption.REPLACE_EXISTING);
+ }
+ public String savePost(Post post) throws IOException {
+ try {
+ String response;
+ URL url = new URL("http://localhost:8000/posts/" + post.getPosterId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ String json = objectMapper.writeValueAsString(post);
+
+ byte[] postDataBytes = json.getBytes();
+
+ con.setRequestMethod("POST");
+ con.setDoOutput(true);
+ con.getOutputStream().write(postDataBytes);
+
+ Reader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ StringBuilder sb = new StringBuilder();
+ for (int c; (c = in.read()) > 0; )
+ sb.append((char) c);
+ response = sb.toString();
+ return response;
+ }
+ catch (ConnectException e) {
+ return "Connection failed";
+ }
+ }
+
+ @FXML
+ void onMouseClickedTextArea(MouseEvent event) {
+ postButton.setVisible(true);
+ }
+
+ @FXML
+ public void initialize() throws IOException {
+ userNameLabel.setText(LoggedInUser.getId());
+ profileImgView.setImage(new Image(downloadProfImg()));
+ URL url = new URL("http://localhost:8000/posts");
+ String response;
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] posts = toStringArray(jsonObject);
+ for (String t : posts) {
+ JSONObject obj = new JSONObject(t);
+ Post post = new Post(obj.getString("posterId"), obj.getString("content"));
+ post.setPostId(obj.getString("postId"));
+ post.setLikesNumber(obj.getInt("likesNumber"));
+ post.setCommentsNumber(obj.getInt("commentsNumber"));
+ post.setTimeStamp(new Date(obj.getLong("timeStamp")));
+
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+ addPostToFeed(post ,post.getContent(), simpleDateFormat.format(new Date(obj.getLong("timeStamp"))), downloadProfPostImg(post.getPosterId()));
+ if (IsLike(LoggedInUser.getId(), post.getPostId())) {
+ Button likeButton = likeButtonsMap.get(post.getPostId());
+ likeButton.setText(Integer.toString(post.getLikesNumber()));
+ likeButton.setStyle("-fx-background-color: #ccc;");
+ }
+ if (isFollowing(LoggedInUser.getId(), post.getPosterId())) {
+ Button followBtn = followButtonsMap.get(post.getPostId());
+ followBtn.setText("followed");
+ followBtn.setOnMouseEntered(event -> followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followBtn.setOnMouseExited(event -> followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white;"));
+ FontAwesomeIconView followIcon = new FontAwesomeIconView(FontAwesomeIcon.CHECK);
+ followIcon.getStyleClass().add("followIcon");
+ followBtn.setGraphic(followIcon);
+ followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white;");
+ }
+ }
+ }
+
+ public static String downloadProfPostImg(String userId) {
+ if (fileExists("C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\profPic" + userId + ".png"))
+ return "C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\profPic" + userId + ".png";
+ return "C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\logo.png";
+ }
+ public static String downloadProfImg() {
+ if (fileExists("C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\profPic" + LoggedInUser.getId() + ".png"))
+ return "C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\profPic" + LoggedInUser.getId() + ".png";
+ return "C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\logo.png";
+ }
+ public void addPostToFeed(Post post, String postContent, String postDate, String profileImagePath) throws IOException {
+ VBox postBox = new VBox(10);
+ postBox.getStyleClass().add("post-box");
+ postBox.setPadding(new Insets(10));
+ postBox.setStyle("-fx-background-color: #ffffff; -fx-border-color: #dddddd; -fx-border-radius: 5; -fx-background-radius: 5;");
+
+ // Profile Image
+ Image profileImage = new Image(profileImagePath);
+ ImageView profileImageView = new ImageView(profileImage);
+ profileImageView.setFitWidth(50);
+ profileImageView.setFitHeight(50);
+ Circle clip = new Circle(25, 25, 25);
+ profileImageView.setClip(clip);
+
+ Label postHeader = new Label(post.getPosterId());
+ postHeader.getStyleClass().add("post-header");
+
+ // Follow Button
+ Button followButton = new Button("Follow");
+ FontAwesomeIconView followIcon = new FontAwesomeIconView(FontAwesomeIcon.USER_PLUS);
+ followIcon.getStyleClass().add("followIcon");
+ followButton.setGraphic(followIcon);
+ followButton.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;");
+ followButton.setOnMouseEntered(event -> followButton.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followButton.setOnMouseExited(event -> followButton.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;"));
+ followButton.setCursor(javafx.scene.Cursor.HAND);
+ followButtonsMap.put(post.getPostId(), followButton);
+ followButton.setOnAction(event -> {
+ try {
+ handleFollow(post, followButton);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+
+ HBox postHeaderBox = new HBox(10, profileImageView, postHeader);
+ postHeaderBox.setAlignment(Pos.CENTER_LEFT);
+
+ // Header with Follow Button
+ HBox headerWithFollow = new HBox(postHeaderBox, followButton);
+ headerWithFollow.setAlignment(Pos.CENTER_LEFT);
+ HBox.setHgrow(postHeaderBox, Priority.ALWAYS);
+ headerWithFollow.setAlignment(Pos.CENTER_RIGHT);
+
+ Label postLabel = new Label(postContent);
+ postLabel.setWrapText(true); // Ensure text wraps within the label
+
+ ScrollPane scrollPane = new ScrollPane();
+ scrollPane.setContent(postLabel);
+ scrollPane.setFitToWidth(true);
+ scrollPane.setPrefHeight(100);
+ scrollPane.getStyleClass().add("scroll-pane-label");
+
+ // Timeline
+ Label timelineLabel = new Label("Posted on: " + postDate);
+ timelineLabel.getStyleClass().add("timeline-label");
+
+ HBox postActions = new HBox(10);
+ postActions.setAlignment(Pos.CENTER);
+
+ Button likeButton = new Button("Like");
+ FontAwesomeIconView thumb = new FontAwesomeIconView(FontAwesomeIcon.THUMBS_UP);
+ thumb.getStyleClass().add("thumbIcon");
+ likeButton.setGraphic(thumb);
+ likeButton.setCursor(javafx.scene.Cursor.HAND);
+ likeButton.getStyleClass().addAll("post-box-btn", "likeBtn");
+ likeButtonsMap.put(post.getPostId(), likeButton);
+
+ Button commentButton = new Button("Comment");
+ FontAwesomeIconView comment = new FontAwesomeIconView(FontAwesomeIcon.COMMENT);
+ comment.getStyleClass().add("commentIcon");
+ commentButton.setGraphic(comment);
+ commentButton.setCursor(javafx.scene.Cursor.HAND);
+ commentButton.getStyleClass().addAll("post-box-btn", "cmtBtn");
+
+ Button shareButton = new Button("Share");
+ FontAwesomeIconView share = new FontAwesomeIconView(FontAwesomeIcon.SHARE);
+ share.getStyleClass().add("shareIcon");
+ shareButton.setGraphic(share);
+ shareButton.setCursor(javafx.scene.Cursor.HAND);
+ shareButton.getStyleClass().addAll("post-box-btn", "shareBtn");
+
+ // Add action listeners using lambdas
+ likeButton.setOnAction(event -> handleLike(post, likeButton));
+ commentButton.setOnAction(event -> {
+ try {
+ handleComment(post);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ shareButton.setOnAction(event -> handleShare(post));
+
+ postActions.getChildren().addAll(likeButton, commentButton, shareButton);
+ // Hidden ImageView
+ // Hidden Image View
+ ImageView hiddenImageView = new ImageView();
+ hiddenImageView.setFitWidth(200);
+ hiddenImageView.setPreserveRatio(true);
+ hiddenImageView.setVisible(false);
+
+ // To center the hidden ImageView
+ StackPane imagePane = new StackPane(hiddenImageView);
+ imagePane.setAlignment(Pos.CENTER);
+ imagePane.setVisible(false); // Initially hidden
+
+ VBox postContentBox = new VBox(5, headerWithFollow, scrollPane, imagePane, timelineLabel, postActions);
+ if (downloadImg(post) != null) {
+ hiddenImageView.setVisible(true);
+ imagePane.setVisible(true);
+ Image img = new Image(downloadImg(post));
+ hiddenImageView.setImage(img);
+ }
+ postBox.getChildren().add(postContentBox);
+
+ feedVBox.getChildren().add(1, postBox);
+ }
+ public static boolean fileExists(String filePath) {
+ File file = new File(filePath);
+ return file.exists() && file.isFile();
+ }
+
+ private String downloadImg(Post post) {
+ if (fileExists("C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\postPic" + post.getPostId() + ".png"))
+ return "C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\postPic" + post.getPostId() + ".png";
+ return null;
+ }
+
+
+ // Example handlers for like, comment, and share actions
+ private void handleLike(Post post, Button likeButton) {
+ try {
+ if (!IsLike(LoggedInUser.getId(), post.getPostId())) {
+ URL url = new URL("http://localhost:8000/likes/" + LoggedInUser.getId() + "/" + post.getPostId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("POST");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful")) {
+ post.addLike();
+ likeButton.setText(Integer.toString(post.getLikesNumber()));
+ likeButton.setStyle("-fx-background-color: #ccc;");
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ else {
+ URL url = new URL("http://localhost:8000/likes/" + LoggedInUser.getId() + "/" + post.getPostId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("DELETE");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful")) {
+ post.takeLike();
+ likeButton.setText(Integer.toString(post.getLikesNumber()));
+ likeButton.setStyle("-fx-background-color: transparent;");
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ public boolean IsLike(String userId, String postId) throws IOException {
+ ArrayList likes = getAllLikes();
+ for (Like l: likes) {
+ if (l.getLiker().equals(userId) && l.getLiked().equals(postId))
+ return true;
+ }
+ return false;
+ }
+
+ public ArrayList getAllLikes() throws IOException {
+ String response;
+ URL url = new URL("http://localhost:8000/likes");
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] users = toStringArray(jsonObject);
+ ArrayList likes = new ArrayList<>();
+ for (String t: users) {
+ JSONObject obj = new JSONObject(t);
+ Like l = new Like(obj.getString("liker"), obj.getString("liked"));
+ likes.add(l);
+ }
+ return likes;
+ }
+
+ private void handleFollow(Post post, Button followBtn) throws IOException {
+ if (!isFollowing(LoggedInUser.getId(), post.getPosterId())) {
+ URL url = new URL("http://localhost:8000/follows/" + LoggedInUser.getId() + "/" + post.getPosterId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("POST");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful!")) {
+ followBtn.setText("followed");
+ followBtn.setOnMouseEntered(event -> followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followBtn.setOnMouseExited(event -> followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white;"));
+ FontAwesomeIconView followIcon = new FontAwesomeIconView(FontAwesomeIcon.CHECK);
+ followIcon.getStyleClass().add("followIcon");
+ followBtn.setGraphic(followIcon);
+ followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white;");
+ changeOtherFollowBtns(post);
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ else {
+ URL url = new URL("http://localhost:8000/follows/" + LoggedInUser.getId() + "/" + post.getPosterId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("DELETE");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful!")) {
+ followBtn.setText("follow");
+ FontAwesomeIconView followIcon = new FontAwesomeIconView(FontAwesomeIcon.USER_PLUS);
+ followIcon.getStyleClass().add("followIcon");
+ followBtn.setGraphic(followIcon);
+ followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;");
+ followBtn.setOnMouseEntered(event -> followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followBtn.setOnMouseExited(event -> followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;"));
+ changeOtherFollowBtns(post);
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+
+ }
+ private void changeOtherFollowBtns(Post post) throws IOException {
+ String response;
+ URL url = new URL("http://localhost:8000/posts");
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] posts1 = toStringArray(jsonObject);
+ for (String t : posts1) {
+ JSONObject obj = new JSONObject(t);
+ if (post.getPosterId().equals(obj.getString("posterId"))) {
+ Button followBtn = followButtonsMap.get(obj.getString("postId"));
+ if (isFollowing(LoggedInUser.getId(), post.getPosterId())) {
+ followBtn.setText("followed");
+ followBtn.setOnMouseEntered(event -> followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followBtn.setOnMouseExited(event -> followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white;"));
+ FontAwesomeIconView followIcon = new FontAwesomeIconView(FontAwesomeIcon.CHECK);
+ followIcon.getStyleClass().add("followIcon");
+ followBtn.setGraphic(followIcon);
+ followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white;");
+ }
+ else {
+ followBtn.setText("follow");
+ FontAwesomeIconView followIcon = new FontAwesomeIconView(FontAwesomeIcon.USER_PLUS);
+ followIcon.getStyleClass().add("followIcon");
+ followBtn.setGraphic(followIcon);
+ followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;");
+ followBtn.setOnMouseEntered(event -> followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followBtn.setOnMouseExited(event -> followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;"));
+ }
+ }
+ }
+ }
+ private ArrayList getAllFollowings(String userId) throws IOException {
+ String response;
+ URL url = new URL("http://localhost:8000/follows/followings/" + userId);
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] follows = toStringArray(jsonObject);
+ ArrayList followings = new ArrayList<>();
+ for (String t: follows) {
+ JSONObject obj = new JSONObject(t);
+ Follow l = new Follow(obj.getString("follower"), obj.getString("followed"));
+ followings.add(l);
+ }
+ return followings;
+ }
+ private boolean isFollowing(String follower, String followed) throws IOException {
+ ArrayList followings = getAllFollowings(follower);
+ for (Follow t: followings) {
+ if (t.getFollowed().equals(followed) && t.getFollower().equals(follower))
+ return true;
+ }
+ return false;
+ }
+
+ private void handleComment(Post post) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ postTextArea.setText("");
+ CommentController.post = post;
+ helloApplication.changeScene(4);
+ }
+
+ private void handleShare(Post post) {
+ // Handle share action
+ System.out.println("Post shared: " + post.getPostId());
+ }
+
+ public static String[] toStringArray(JSONArray array) {
+ if(array == null)
+ return new String[0];
+
+ String[] arr = new String[array.length()];
+ for(int i = 0; i < arr.length; i++)
+ arr[i] = array.optString(i);
+ return arr;
+ }
+
+ public void meBtnClicked(ActionEvent actionEvent) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ postTextArea.setText("");
+ helloApplication.changeScene(5);
+ }
+}
+
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/Follow.java b/LinkedInClient/src/main/java/org/example/linkedinclient/Follow.java
new file mode 100644
index 0000000..6926ff9
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/Follow.java
@@ -0,0 +1,33 @@
+package org.example.linkedinclient;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Follow {
+ @JsonProperty("follower")
+ private String follower;
+ @JsonProperty("followed")
+ private String followed;
+
+ public Follow(String follower, String followed) {
+ this.follower = follower;
+ this.followed = followed;
+ }
+ public Follow() {}
+
+ public String getFollower() {
+ return follower;
+ }
+
+ public void setFollower(String follower) {
+ this.follower = follower;
+ }
+
+ public String getFollowed() {
+ return followed;
+ }
+
+ public void setFollowed(String followed) {
+ this.followed = followed;
+ }
+}
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/FollowersPageController.java b/LinkedInClient/src/main/java/org/example/linkedinclient/FollowersPageController.java
new file mode 100644
index 0000000..d927f6f
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/FollowersPageController.java
@@ -0,0 +1,185 @@
+package org.example.linkedinclient;
+
+import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon;
+import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Region;
+import javafx.scene.layout.VBox;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import static org.example.linkedinclient.FeedController.downloadProfPostImg;
+import static org.example.linkedinclient.FeedController.toStringArray;
+import static org.example.linkedinclient.HelloApplication.LoggedInUser;
+import static org.example.linkedinclient.ProfileViewController.getFollowers;
+
+public class FollowersPageController {
+
+ @FXML
+ private VBox followersContainer;
+ HashMap followButtonsMap = new HashMap<>();
+
+ public void initialize() throws IOException {
+ ArrayList followers = getFollowers();
+ for (User user: followers) {
+ addFollower(user, downloadProfPostImg(user.getId()));
+ if (isFollowing(LoggedInUser.getId(), user.getId())) {
+ Button followBtn = followButtonsMap.get(user.getId());
+ followBtn.setText("followed");
+ followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white; -fx-padding: 5 10; -fx-font-family: 'Segoe UI'; -fx-font-size: 14px;");
+ }
+ }
+ }
+ public static void handleFollowButton(User user, Button followButton) throws IOException {
+ saveFollow(user, followButton);
+ }
+ public static void saveFollow(User user, Button followBtn) throws IOException {
+ if (!isFollowing(LoggedInUser.getId(), user.getId())) {
+ URL url = new URL("http://localhost:8000/follows/" + LoggedInUser.getId() + "/" + user.getId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("POST");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful!")) {
+ followBtn.setText("followed");
+ followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white; -fx-padding: 5 10; -fx-font-family: 'Segoe UI'; -fx-font-size: 14px;");
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ else {
+ URL url = new URL("http://localhost:8000/follows/" + LoggedInUser.getId() + "/" + user.getId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("DELETE");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful!")) {
+ followBtn.setText("follow");
+ followBtn.setStyle("-fx-background-color: #0073b1; -fx-text-fill: white; -fx-padding: 5 10; -fx-font-family: 'Segoe UI'; -fx-font-size: 14px;");
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ }
+ private static ArrayList getAllFollowings(String userId) throws IOException {
+ String response;
+ URL url = new URL("http://localhost:8000/follows/followings/" + userId);
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] follows = toStringArray(jsonObject);
+ ArrayList followings = new ArrayList<>();
+ for (String t: follows) {
+ JSONObject obj = new JSONObject(t);
+ Follow l = new Follow(obj.getString("follower"), obj.getString("followed"));
+ followings.add(l);
+ }
+ return followings;
+ }
+ private static boolean isFollowing(String follower, String followed) throws IOException {
+ ArrayList followings = getAllFollowings(follower);
+ for (Follow t: followings) {
+ if (t.getFollowed().equals(followed) && t.getFollower().equals(follower))
+ return true;
+ }
+ return false;
+ }
+ public void addFollower(User user, String profileImageUrl) {
+ // Create a new HBox for the follower
+ HBox followerBox = new HBox();
+ followerBox.setSpacing(10.0);
+ followerBox.setStyle("-fx-alignment: center-left;");
+
+ // Create an ImageView for the profile image
+ ImageView profileImageView = new ImageView(new Image(profileImageUrl));
+ profileImageView.setFitHeight(50.0);
+ profileImageView.setFitWidth(50.0);
+ profileImageView.setStyle("-fx-shape: 'M 0.5, 0 A 0.5, 0.5 0 1,0 1,0.5 A 0.5, 0.5 0 1,0 0.5,0 Z'; -fx-clip: true;");
+
+
+ Region region = new Region();
+ region.setPrefHeight(Region.USE_COMPUTED_SIZE);
+ region.setPrefWidth(Region.USE_COMPUTED_SIZE);
+ HBox.setHgrow(region, javafx.scene.layout.Priority.ALWAYS);
+
+ // Create a Label for the follower ID
+ Label followerIdLabel = new Label(user.getId());
+ followerIdLabel.setStyle("-fx-font-family: 'Segoe UI'; -fx-font-size: 16px;");
+
+ // Create a follow button
+ Button followButton = new Button("Follow");
+ followButton.setStyle("-fx-background-color: #0073b1; -fx-text-fill: white; -fx-padding: 5 10; -fx-font-family: 'Segoe UI'; -fx-font-size: 14px;");
+ followButton.setCursor(javafx.scene.Cursor.HAND);
+ followButtonsMap.put(user.getId(), followButton);
+ followButton.setOnAction(e -> {
+ try {
+ handleFollowButton(user, followButton);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ });
+
+ // Add all elements to the HBox
+ followerBox.getChildren().addAll(profileImageView, followerIdLabel, region, followButton);
+
+ // Add the HBox to the followers container
+ followersContainer.getChildren().add(followerBox);
+ }
+
+ public void closeBtnClicked(ActionEvent actionEvent) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(5);
+ }
+ public static String[] toStringArray(JSONArray array) {
+ if(array == null)
+ return new String[0];
+
+ String[] arr = new String[array.length()];
+ for(int i = 0; i < arr.length; i++)
+ arr[i] = array.optString(i);
+ return arr;
+ }
+}
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/FollowingsPageController.java b/LinkedInClient/src/main/java/org/example/linkedinclient/FollowingsPageController.java
new file mode 100644
index 0000000..d1a943e
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/FollowingsPageController.java
@@ -0,0 +1,182 @@
+package org.example.linkedinclient;
+
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Region;
+import javafx.scene.layout.VBox;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import static org.example.linkedinclient.FeedController.downloadProfPostImg;
+import static org.example.linkedinclient.HelloApplication.LoggedInUser;
+import static org.example.linkedinclient.ProfileViewController.getFollowers;
+import static org.example.linkedinclient.ProfileViewController.getFollowings;
+
+public class FollowingsPageController {
+ @FXML
+ private VBox followersContainer;
+ HashMap followButtonsMap = new HashMap<>();
+
+ public void initialize() throws IOException {
+ ArrayList followings = getFollowings();
+ for (User user: followings) {
+ addFollowing(user, downloadProfPostImg(user.getId()));
+ if (isFollowing(LoggedInUser.getId(), user.getId())) {
+ Button followBtn = followButtonsMap.get(user.getId());
+ followBtn.setText("followed");
+ followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white; -fx-padding: 5 10; -fx-font-family: 'Segoe UI'; -fx-font-size: 14px;");
+ }
+ }
+ }
+ public static void handleFollowButton(User user, Button followButton) throws IOException {
+ saveFollow(user, followButton);
+ }
+ public static void saveFollow(User user, Button followBtn) throws IOException {
+ if (!isFollowing(LoggedInUser.getId(), user.getId())) {
+ URL url = new URL("http://localhost:8000/follows/" + LoggedInUser.getId() + "/" + user.getId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("POST");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful!")) {
+ followBtn.setText("followed");
+ followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white; -fx-padding: 5 10; -fx-font-family: 'Segoe UI'; -fx-font-size: 14px;");
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ else {
+ URL url = new URL("http://localhost:8000/follows/" + LoggedInUser.getId() + "/" + user.getId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("DELETE");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful!")) {
+ followBtn.setText("follow");
+ followBtn.setStyle("-fx-background-color: #0073b1; -fx-text-fill: white; -fx-padding: 5 10; -fx-font-family: 'Segoe UI'; -fx-font-size: 14px;");
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ }
+ private static ArrayList getAllFollowings() throws IOException {
+ String response;
+ URL url = new URL("http://localhost:8000/follows");
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] follows = toStringArray(jsonObject);
+ ArrayList followings = new ArrayList<>();
+ for (String t: follows) {
+ JSONObject obj = new JSONObject(t);
+ Follow l = new Follow(obj.getString("follower"), obj.getString("followed"));
+ followings.add(l);
+ }
+ return followings;
+ }
+ private static boolean isFollowing(String follower, String followed) throws IOException {
+ ArrayList followings = getAllFollowings();
+ for (Follow t: followings) {
+ if (t.getFollowed().equals(followed) && t.getFollower().equals(follower))
+ return true;
+ }
+ return false;
+ }
+ public void addFollowing(User user, String profileImageUrl) {
+ // Create a new HBox for the follower
+ HBox followerBox = new HBox();
+ followerBox.setSpacing(10.0);
+ followerBox.setStyle("-fx-alignment: center-left;");
+
+ // Create an ImageView for the profile image
+ ImageView profileImageView = new ImageView(new Image(profileImageUrl));
+ profileImageView.setFitHeight(50.0);
+ profileImageView.setFitWidth(50.0);
+ profileImageView.setStyle("-fx-shape: 'M 0.5, 0 A 0.5, 0.5 0 1,0 1,0.5 A 0.5, 0.5 0 1,0 0.5,0 Z'; -fx-clip: true;");
+
+
+ Region region = new Region();
+ region.setPrefHeight(Region.USE_COMPUTED_SIZE);
+ region.setPrefWidth(Region.USE_COMPUTED_SIZE);
+ HBox.setHgrow(region, javafx.scene.layout.Priority.ALWAYS);
+
+ // Create a Label for the follower ID
+ Label followerIdLabel = new Label(user.getId());
+ followerIdLabel.setStyle("-fx-font-family: 'Segoe UI'; -fx-font-size: 16px;");
+
+ // Create a follow button
+ Button followButton = new Button("Follow");
+ followButton.setStyle("-fx-background-color: #0073b1; -fx-text-fill: white; -fx-padding: 5 10; -fx-font-family: 'Segoe UI'; -fx-font-size: 14px;");
+ followButton.setCursor(javafx.scene.Cursor.HAND);
+ followButtonsMap.put(user.getId(), followButton);
+ followButton.setOnAction(e -> {
+ try {
+ handleFollowButton(user, followButton);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ });
+
+ // Add all elements to the HBox
+ followerBox.getChildren().addAll(profileImageView, followerIdLabel, region, followButton);
+
+ // Add the HBox to the followers container
+ followersContainer.getChildren().add(followerBox);
+ }
+
+ public void closeBtnClicked(ActionEvent actionEvent) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(5);
+ }
+ public static String[] toStringArray(JSONArray array) {
+ if(array == null)
+ return new String[0];
+
+ String[] arr = new String[array.length()];
+ for(int i = 0; i < arr.length; i++)
+ arr[i] = array.optString(i);
+ return arr;
+ }
+}
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/HelloApplication.java b/LinkedInClient/src/main/java/org/example/linkedinclient/HelloApplication.java
new file mode 100644
index 0000000..cc4f5c7
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/HelloApplication.java
@@ -0,0 +1,78 @@
+package org.example.linkedinclient;
+
+import javafx.application.Application;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.Scene;
+import javafx.scene.image.Image;
+import javafx.stage.Stage;
+
+import java.io.IOException;
+
+public class HelloApplication extends Application {
+ private static Stage stg;
+ private static Scene Login;
+ public static User LoggedInUser;
+ public static String token;
+
+ @Override
+ public void start(Stage stage) throws IOException, InterruptedException {
+ stg = stage;
+ stage.setResizable(false);
+ Login = new Scene((new FXMLLoader(HelloApplication.class.getResource("login.fxml"))).load(), 700, 500);
+ stage.setTitle("LinkedIn");
+ Image icon = new Image("C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\img\\logo.png");
+ stage.getIcons().add(icon);
+ stg.setScene(Login);
+ stage.show();
+ }
+ public void changeScene(int x) throws IOException {
+ switch (x) {
+ case 1:
+ stg.setScene(Login);
+ break;
+ case 2:
+ stg.setScene(new Scene((new FXMLLoader(HelloApplication.class.getResource("signIn.fxml"))).load()));
+ break;
+ case 3:
+ stg.setScene(new Scene((new FXMLLoader(HelloApplication.class.getResource("LinkedInFeed.fxml"))).load(), 1000, 600));
+ break;
+ case 4:
+ stg.setScene(new Scene((new FXMLLoader(HelloApplication.class.getResource("commentSection.fxml"))).load(), 1000, 800));
+ break;
+ case 5:
+ stg.setScene(new Scene((new FXMLLoader(HelloApplication.class.getResource("profileView.fxml"))).load(), 800, 1000));
+ break;
+ case 6:
+ stg.setScene(new Scene((new FXMLLoader(HelloApplication.class.getResource("educationsView.fxml"))).load(), 600, 1000));
+ break;
+ case 7:
+ stg.setScene(new Scene((new FXMLLoader(HelloApplication.class.getResource("educationComponent.fxml"))).load(), 600, 1000));
+ break;
+ case 8:
+ stg.setScene(new Scene((new FXMLLoader(HelloApplication.class.getResource("sumPage.fxml"))).load(), 600, 500));
+ break;
+ case 9:
+ stg.setScene(new Scene((new FXMLLoader(HelloApplication.class.getResource("skillPage.fxml"))).load(), 432, 602));
+ break;
+ case 10:
+ stg.setScene(new Scene((new FXMLLoader(HelloApplication.class.getResource("skillComponent.fxml"))).load(), 400, 300));
+ break;
+ case 11:
+ stg.setScene(new Scene((new FXMLLoader(HelloApplication.class.getResource("followersPage.fxml"))).load(), 600, 700));
+ break;
+ case 12:
+ stg.setScene(new Scene((new FXMLLoader(HelloApplication.class.getResource("followingsPage.fxml"))).load(), 600, 700));
+ break;
+ case 13:
+ stg.setScene(new Scene((new FXMLLoader(HelloApplication.class.getResource("userProfilePage.fxml"))).load(), 800, 1000));
+ break;
+
+
+ }
+
+ }
+
+ public static void main(String[] args) {
+ launch();
+ }
+}
\ No newline at end of file
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/Like.java b/LinkedInClient/src/main/java/org/example/linkedinclient/Like.java
new file mode 100644
index 0000000..f825ece
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/Like.java
@@ -0,0 +1,45 @@
+package org.example.linkedinclient;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Like {
+ @JsonProperty("liker")
+ private String liker;
+
+ @JsonProperty("liked")
+ private String liked;
+
+ public Like () {
+
+ }
+
+ public Like(String liker, String liked) {
+ this.liker = liker;
+ this.liked = liked;
+ }
+
+ public String getLiker() {
+ return liker;
+ }
+
+ public void setLiker(String liker) {
+ this.liker = liker;
+ }
+
+ public String getLiked() {
+ return liked;
+ }
+
+ public void setLiked(String liked) {
+ this.liked = liked;
+ }
+
+ @Override
+ public String toString() {
+ return "Like{" +
+ "liker='" + liker + '\'' +
+ ", liked='" + liked + '\'' +
+ '}';
+ }
+}
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/LogInController.java b/LinkedInClient/src/main/java/org/example/linkedinclient/LogInController.java
new file mode 100644
index 0000000..1bee946
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/LogInController.java
@@ -0,0 +1,121 @@
+package org.example.linkedinclient;
+
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.Button;
+import javafx.scene.control.Hyperlink;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.control.Label;
+import javafx.scene.control.PasswordField;
+import javafx.scene.control.TextField;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+
+public class LogInController {
+
+ @FXML
+ private PasswordField PassWord;
+
+ @FXML
+ private Hyperlink forgetPassLink;
+
+ @FXML
+ private Button logInBtn;
+
+ @FXML
+ private Button signInBtn;
+
+ @FXML
+ private TextField userName;
+
+ @FXML
+ private Label wrong;
+ private void clear() {
+ PassWord.setText("");
+ userName.setText("");
+ wrong.setText("");
+ }
+ @FXML
+ void onMouseEnteredLogin(MouseEvent event) {
+ logInBtn.setStyle("-fx-background-color: #007fd3;");
+ }
+
+ @FXML
+ void onMouseEnteredSignIn(MouseEvent event) {
+ signInBtn.setStyle("-fx-background-color: #222527;");
+ }
+
+ @FXML
+ void onMouseExitedLogin(MouseEvent event) {
+ logInBtn.setStyle("-fx-background-color: #0598ff;");
+ }
+
+ @FXML
+ void onMouseExitedSignIn(MouseEvent event) {
+ signInBtn.setStyle("-fx-background-color: #000000;");
+ }
+
+ @FXML
+ void loginBtnClicked(MouseEvent event) throws IOException {
+ if (userName.getText().length() == 0 || PassWord.getText().length() == 0) {
+ wrong.setText("PLEASE ENTER ALL OF THE FIELDS!");
+ }
+ else {
+ URL url = new URL("http://localhost:8000/sessions/" + userName.getText() + "/" + PassWord.getText());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+ HelloApplication.token = con.getHeaderField("JWT");
+ if (response.equals("userID or PassWord is incorrect")) {
+ wrong.setText("Username or Password is incorrect!");
+ }
+ else {
+ HelloApplication m = new HelloApplication();
+ url = new URL("http://localhost:8000/users/" + userName.getText());
+ con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ responseCode = con.getResponseCode();
+ BufferedReader in1 = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline1;
+ StringBuffer response2 = new StringBuffer();
+ while ((inputline1 = in1.readLine()) != null) {
+ response2.append(inputline1);
+ }
+ in.close();
+ response = response2.toString();
+ JSONObject obj = new JSONObject(response);
+ if (!obj.getString("id").equals(userName.getText()))
+ wrong.setText("Username or Password is incorrect!");
+ else {
+ User user = new User(obj.getString("id"), obj.getString("firstName"), obj.getString("lastName"), obj.getString("additionalName"), obj.getString("country"), obj.getString("city"), obj.getString("email"), obj.getString("password"), obj.getString("phoneNumber"), obj.getInt("followers"), obj.getInt("followings"));
+ HelloApplication.LoggedInUser = user;
+ clear();
+ m.changeScene(3);
+ }
+ }
+ }
+
+ }
+
+ @FXML
+ void signInClicked(ActionEvent event) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ clear();
+ helloApplication.changeScene(2);
+ }
+
+}
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/Post.java b/LinkedInClient/src/main/java/org/example/linkedinclient/Post.java
new file mode 100644
index 0000000..e4a0657
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/Post.java
@@ -0,0 +1,15 @@
+package org.example.linkedinclient;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.Date;
+
+
+public class Post extends Content {
+ public Post(String posterId, String content) {
+ super(posterId, content);
+ }
+ public Post() {
+ super();
+ }
+}
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/ProfileViewController.java b/LinkedInClient/src/main/java/org/example/linkedinclient/ProfileViewController.java
new file mode 100644
index 0000000..de215e7
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/ProfileViewController.java
@@ -0,0 +1,285 @@
+package org.example.linkedinclient;
+
+import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.fxml.Initializable;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextArea;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.VBox;
+import javafx.stage.FileChooser;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ResourceBundle;
+
+import static org.example.linkedinclient.FeedController.toStringArray;
+import static org.example.linkedinclient.HelloApplication.LoggedInUser;
+
+public class ProfileViewController {
+
+ @FXML
+ private Button changePicBtn;
+
+ @FXML
+ private FontAwesomeIconView closeBtn;
+
+ @FXML
+ private FontAwesomeIconView editEduBtn;
+
+ @FXML
+ private FontAwesomeIconView editSkillBtn;
+
+ @FXML
+ private FontAwesomeIconView editSumBtn;
+
+ @FXML
+ private VBox educationVBox;
+
+ @FXML
+ private Label emailLabel;
+
+ @FXML
+ private Label followersCountLabel;
+
+ @FXML
+ private Label followersLabel;
+
+ @FXML
+ private Label followingsCountLabel;
+
+ @FXML
+ private Label followingsLabel;
+
+ @FXML
+ private Label headlineLabel;
+
+ @FXML
+ private Button logOutBtn;
+
+ @FXML
+ private Label nameLabel;
+
+ @FXML
+ private Label phoneLabel;
+
+ @FXML
+ private ImageView profileImageView;
+
+ @FXML
+ private VBox skillsVBox;
+
+ @FXML
+ private TextArea summaryTextArea;
+ @FXML
+ public void initialize() throws IOException {
+ profileImageView.setImage(new Image(downloadImg()));
+ nameLabel.setText(LoggedInUser.getId());
+ headlineLabel.setText(LoggedInUser.getCountry() + ", " + LoggedInUser.getCity());
+ emailLabel.setText(LoggedInUser.getEmail());
+ phoneLabel.setText(LoggedInUser.getPhoneNumber());
+ ArrayList followers = getFollowers();
+ ArrayList followings = getFollowings();
+ followersCountLabel.setText(Integer.toString(followers.size()));
+ followingsCountLabel.setText(Integer.toString(followings.size()));
+ getBio();
+
+ }
+
+ @FXML
+ void OnMouseClickedCloseBtn(MouseEvent event) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(3);
+ }
+
+ @FXML
+ void OnMouseClickededitEduBtn(MouseEvent event) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(6);
+ }
+
+ @FXML
+ void OnMouseClickededitSkillBtn(MouseEvent event) {
+
+ }
+
+ @FXML
+ void OnMouseClickededitSumBtn(MouseEvent event) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(8);
+ }
+
+ @FXML
+ void changePicClicked(ActionEvent event) throws IOException {
+ FileChooser fc = new FileChooser();
+ fc.getExtensionFilters().add(new FileChooser.ExtensionFilter("pictures", "*.png"));
+ List f = fc.showOpenMultipleDialog(null);
+ String res = "";
+ if (f == null)
+ return;
+ for (int i = 0; i < f.size(); i++) {
+ File file = f.get(i);
+ res += file.getName();
+
+ if (i != f.size() - 1)
+ res += ", ";
+ }
+ if (f.get(0) != null) {
+ copyFileToDirectory(f.get(0), "C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets", "profPic" + LoggedInUser.getId() + ".png");
+ profileImageView.setImage(new Image(downloadImg()));
+ }
+
+ }
+ private void copyFileToDirectory(File file, String targetDirectory, String newName) throws IOException {
+ Path targetPath = Path.of(targetDirectory, newName);
+ Files.copy(file.toPath(), targetPath, StandardCopyOption.REPLACE_EXISTING);
+ }
+ private String downloadImg() {
+ if (fileExists("C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\profPic" + LoggedInUser.getId() + ".png"))
+ return "C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\profPic" + LoggedInUser.getId() + ".png";
+ return "C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\logo.png";
+ }
+ public static boolean fileExists(String filePath) {
+ File file = new File(filePath);
+ return file.exists() && file.isFile();
+ }
+
+
+ @FXML
+ void logOutClicked(ActionEvent event) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ LoggedInUser = null;
+ helloApplication.changeScene(1);
+ }
+
+ public void OnMouseClickedShowFollowersBtn(MouseEvent mouseEvent) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(11);
+ }
+
+ public void OnMouseClickedShowFollowingsBtn(MouseEvent mouseEvent) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(12);
+ }
+
+ public void OnMouseClickedSumBtn(MouseEvent mouseEvent) {
+ }
+
+ public void OnMouseClickedEduBtn(MouseEvent mouseEvent) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(6);
+ }
+ public static ArrayList getFollowers() throws IOException {
+ URL url = new URL("http://localhost:8000/follows/followers/" + LoggedInUser.getId());
+ String response;
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] users = toStringArray(jsonObject);
+ ArrayList users1 = new ArrayList<>();
+ for (String t: users) {
+ JSONObject obj = new JSONObject(t);
+ User user = getUser(obj.getString("follower"));
+ users1.add(user);
+ }
+ return users1;
+ }
+ public static User getUser(String userId) throws IOException {
+ String response;
+ URL url = new URL("http://localhost:8000/users/" + userId);
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ responseCode = con.getResponseCode();
+ BufferedReader in1 = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline1;
+ StringBuffer response2 = new StringBuffer();
+ while ((inputline1 = in1.readLine()) != null) {
+ response2.append(inputline1);
+ }
+ in1.close();
+ response = response2.toString();
+ JSONObject obj = new JSONObject(response);
+ User user = new User(userId, obj.getString("firstName"), obj.getString("lastName"), obj.getString("additionalName"), obj.getString("country"), obj.getString("city"), obj.getString("email"), obj.getString("password"), obj.getString("phoneNumber"), obj.getInt("followers"), obj.getInt("followings"));
+ return user;
+ }
+ public static ArrayList getFollowings() throws IOException {
+ URL url = new URL("http://localhost:8000/follows/followings/" + LoggedInUser.getId());
+ String response;
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] users = toStringArray(jsonObject);
+ ArrayList users1 = new ArrayList<>();
+ for (String t: users) {
+ JSONObject obj = new JSONObject(t);
+ User user = getUser(obj.getString("followed"));
+ users1.add(user);
+ }
+ return users1;
+ }
+ private void getBio() throws IOException {
+ String response;
+ URL url = new URL("http://localhost:8000/bios/" + LoggedInUser.getId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ responseCode = con.getResponseCode();
+ BufferedReader in1 = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline1;
+ StringBuffer response2 = new StringBuffer();
+ while ((inputline1 = in1.readLine()) != null) {
+ response2.append(inputline1);
+ }
+ in1.close();
+ response = response2.toString();
+ if (!response.equals("NO BIO!")) {
+ JSONObject obj = new JSONObject(response);
+ summaryTextArea.setText(obj.getString("bioText"));
+ }
+ else
+ summaryTextArea.setText("Add A Summary For YourSelf");
+
+
+ }
+ public void OnMouseClickedSkillBtn(MouseEvent mouseEvent) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(9);
+ }
+}
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/SignInController.java b/LinkedInClient/src/main/java/org/example/linkedinclient/SignInController.java
new file mode 100644
index 0000000..4bf4f41
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/SignInController.java
@@ -0,0 +1,237 @@
+package org.example.linkedinclient;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import javafx.fxml.FXML;
+import javafx.scene.control.Button;
+import javafx.scene.control.PasswordField;
+import javafx.scene.control.SplitMenuButton;
+import javafx.scene.control.TextField;
+import javafx.scene.input.MouseEvent;
+import javafx.event.ActionEvent;
+import javafx.scene.control.MenuItem;
+import javafx.scene.control.Label;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+
+public class SignInController {
+
+ @FXML
+ private Button LoginBtn;
+
+ @FXML
+ private PasswordField PassWord;
+
+ @FXML
+ private Button SignInBtn;
+
+ @FXML
+ private MenuItem USA;
+
+ @FXML
+ private TextField additionalName;
+
+ @FXML
+ private MenuItem canada;
+
+ @FXML
+ private TextField city;
+
+ @FXML
+ private SplitMenuButton countryChosser;
+
+ @FXML
+ private TextField email;
+
+ @FXML
+ private TextField firstName;
+
+ @FXML
+ private MenuItem iran;
+
+ @FXML
+ private TextField lastName;
+
+ @FXML
+ private TextField number;
+
+ @FXML
+ private PasswordField rePassWord;
+
+ @FXML
+ private TextField userName;
+
+ @FXML
+ private Label wrongLable;
+
+ private void clear() {
+ rePassWord.setText("");
+ PassWord.setText("");
+ userName.setText("");
+ additionalName.setText("");
+ firstName.setText("");
+ lastName.setText("");
+ wrongLable.setText("");
+ email.setText("");
+ number.setText("");
+ countryChosser.setText("Choose Your Country");
+ city.setText("");
+ }
+
+ @FXML
+ void LoginBtnClicked(MouseEvent event) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ clear();
+ helloApplication.changeScene(1);
+ }
+
+ @FXML
+ void SignInBtnClicked(MouseEvent event) throws IOException {
+ boolean a1 = firstName.getText().length() == 0;
+ boolean a2 = lastName.getText().length() == 0;
+ boolean a3 = userName.getText().length() == 0;
+ boolean a4 = PassWord.getText().length() == 0;
+ boolean a5 = email.getText().length() == 0;
+ boolean a6 = number.getText().length() == 0;
+ boolean a7 = countryChosser.getText().equals("Choose Your Country");
+ boolean a8 = rePassWord.getText().length() == 0;
+ if (a1 || a2 || a3 || a4 || a5 || a6 || a7 || a8)
+ wrongLable.setText("PLEASE ENTER ALL FIELDS!");
+ else if (!isValidEmailAddress(email.getText()))
+ wrongLable.setText("NOT A VALID EMAIL!");
+ else if (!PassWord.getText().equals(rePassWord.getText()))
+ wrongLable.setText("PASSWORDS DO NOT MATCH!");
+ else {
+ URL url = new URL("http://localhost:8000/users");
+ String response;
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] users = toStringArray(jsonObject);
+ boolean Email_existed = false;
+ for (String t: users) {
+ JSONObject obj = new JSONObject(t);
+ User user = new User(obj.getString("id"), obj.getString("firstName"), obj.getString("lastName"), obj.getString("additionalName"), obj.getString("country"), obj.getString("city"), obj.getString("email"), obj.getString("password"), obj.getString("phoneNumber") , 0, 0);
+ if (user.getEmail().equals(email.getText()) && email.getText().length() != 0)
+ Email_existed = true;
+ if (user.getPhoneNumber().equals(number.getText()) && number.getText().length() != 0)
+ Email_existed = true;
+ }
+ if (Email_existed) {
+ wrongLable.setText("Email or Phone existed");
+ }
+ else {
+
+ url = new URL("http://localhost:8000/users/" + userName.getText());
+ con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ responseCode = con.getResponseCode();
+ in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+
+ if (!response.equals("No User")) {
+ wrongLable.setText("Username exist");
+ }
+ else {
+ url = new URL("http://localhost:8000/users");
+ con = (HttpURLConnection) url.openConnection();
+ User user = new User(userName.getText(), firstName.getText(), lastName.getText(), additionalName.getText(), countryChosser.getText(), city.getText(), email.getText(), PassWord.getText(), number.getText(), 0 , 0);
+ ObjectMapper objectMapper = new ObjectMapper();
+ String json = objectMapper.writeValueAsString(user);
+ byte[] postDataBytes = json.getBytes();
+ con.setRequestMethod("POST");
+ con.setDoOutput(true);
+ con.getOutputStream().write(postDataBytes);
+
+ Reader in1 = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ StringBuilder sb = new StringBuilder();
+ for (int c; (c = in1.read()) > 0; )
+ sb.append((char) c);
+ response = sb.toString();
+ if (response.equals("successful!")) {
+ clear();
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(1);
+
+ } else
+ wrongLable.setText("Server error");
+
+ }
+ }
+ }
+
+ }
+
+ public static boolean isValidEmailAddress(String emailAddress) {
+ String ePattern = "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$";
+ java.util.regex.Pattern p = java.util.regex.Pattern.compile(ePattern);
+ java.util.regex.Matcher m = p.matcher(emailAddress);
+ return m.matches();
+ }
+ public static String[] toStringArray(JSONArray array) {
+ if(array == null)
+ return new String[0];
+
+ String[] arr = new String[array.length()];
+ for(int i = 0; i < arr.length; i++)
+ arr[i] = array.optString(i);
+ return arr;
+ }
+ @FXML
+ void USAClicked(ActionEvent event) {
+ countryChosser.setText("USA");
+
+ }
+
+ @FXML
+ void canadaClicked(ActionEvent event) {
+ countryChosser.setText("Canada");
+ }
+
+ @FXML
+ void iranClicked(ActionEvent event) {
+ countryChosser.setText("Iran");
+ }
+
+ @FXML
+ void onMouseEnteredLogin(MouseEvent event) {
+ LoginBtn.setStyle("-fx-background-color: #222527;");
+ }
+
+ @FXML
+ void onMouseEnteredSignIn(MouseEvent event) {
+ SignInBtn.setStyle("-fx-background-color: #007fd3;");
+ }
+
+ @FXML
+ void onMouseExitedLogin(MouseEvent event) {
+ LoginBtn.setStyle("-fx-background-color: #000000;");
+ }
+
+ @FXML
+ void onMouseExitedSignIn(MouseEvent event) {
+ SignInBtn.setStyle("-fx-background-color: #0598ff;");
+ }
+
+}
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/Skill.java b/LinkedInClient/src/main/java/org/example/linkedinclient/Skill.java
new file mode 100644
index 0000000..42ae867
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/Skill.java
@@ -0,0 +1,45 @@
+package org.example.linkedinclient;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Skill {
+ @JsonProperty("userId")
+ private String userId;
+ @JsonProperty("nthSkill")
+ private int nthSkill;
+ @JsonProperty("text")
+ private String text;
+
+ public Skill(String userId, int nthSkill, String text) {
+ this.userId = userId;
+ this.nthSkill = nthSkill;
+ this.text = text;
+ }
+
+ public Skill() {}
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+
+ public int getNthSkill() {
+ return nthSkill;
+ }
+
+ public void setNthSkill(int nthSkill) {
+ this.nthSkill = nthSkill;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+}
+
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/SkillComponentController.java b/LinkedInClient/src/main/java/org/example/linkedinclient/SkillComponentController.java
new file mode 100644
index 0000000..c4aa3e9
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/SkillComponentController.java
@@ -0,0 +1,73 @@
+package org.example.linkedinclient;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextField;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import static org.example.linkedinclient.HelloApplication.LoggedInUser;
+
+public class SkillComponentController {
+ @FXML
+ private TextField skillField;
+
+ @FXML
+ private Label wrongLabel;
+
+ public void handleCancel(ActionEvent actionEvent) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ skillField.setText("");
+ helloApplication.changeScene(9);
+ }
+ private void saveSkill() throws IOException {
+ String response;
+ URL url = new URL("http://localhost:8000/skills/" + LoggedInUser.getId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ Skill skill = new Skill(LoggedInUser.getId(), 1, skillField.getText());
+ ObjectMapper objectMapper = new ObjectMapper();
+ String json = objectMapper.writeValueAsString(skill);
+
+ byte[] postDataBytes = json.getBytes();
+
+ con.setRequestMethod("POST");
+ con.setDoOutput(true);
+ con.getOutputStream().write(postDataBytes);
+
+ try (Reader in = new BufferedReader(new InputStreamReader(con.getInputStream()))) {
+ StringBuilder sb = new StringBuilder();
+ for (int c; (c = in.read()) > 0; ) {
+ sb.append((char) c);
+ }
+ response = sb.toString();
+ }
+
+ if (response.equals("successful")) {
+ HelloApplication helloApplication = new HelloApplication();
+ skillField.setText("");
+ helloApplication.changeScene(9);
+ } else {
+ System.out.println("Server response: " + response);
+ wrongLabel.setVisible(true);
+ wrongLabel.setText(response);
+ }
+ }
+
+ public void handleSave(ActionEvent actionEvent) throws IOException {
+ if (skillField.getText().isEmpty()) {
+ wrongLabel.setText("PLEASE WRITE SOMETHING!!!");
+ wrongLabel.setVisible(true);
+ }
+ else
+ saveSkill();
+ }
+}
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/SkillPageController.java b/LinkedInClient/src/main/java/org/example/linkedinclient/SkillPageController.java
new file mode 100644
index 0000000..1017b9e
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/SkillPageController.java
@@ -0,0 +1,147 @@
+package org.example.linkedinclient;
+
+
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.Cursor;
+import javafx.scene.control.Button;
+import javafx.scene.control.TextArea;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.VBox;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import static org.example.linkedinclient.HelloApplication.LoggedInUser;
+
+public class SkillPageController {
+
+ @FXML
+ private Button closeBtn;
+
+ @FXML
+ private Button addSkillBtn;
+
+ @FXML
+ private VBox skillsContainer;
+
+ private int skillCount = 0;
+
+ public void initialize() throws IOException {
+ ArrayList skills = getSkills();
+ if (!skills.isEmpty()) {
+ for (Skill skill : skills) {
+ addSkill(skill.getText(), skill.getNthSkill());
+ }
+ }
+ }
+ @FXML
+ private void handleClose(ActionEvent event) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(5);
+ }
+
+ @FXML
+ private void handleAddSkill(ActionEvent event) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(10);
+ }
+
+ private void addSkill(String skillText, int nthSkill) {
+ skillCount++;
+ HBox skillItem = new HBox(10);
+ skillItem.setAlignment(javafx.geometry.Pos.CENTER_LEFT);
+ skillItem.getStyleClass().add("skill-item");
+
+ Button removeButton = new Button("X");
+ removeButton.setCursor(Cursor.HAND);
+ removeButton.setOnAction(e -> {
+ try {
+ handleRemoveSkill(skillItem, nthSkill);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ });
+ removeButton.setStyle("-fx-background-color: transparent;");
+ removeButton.getStyleClass().add("remove-button");
+
+ TextArea skillTextArea = new TextArea(skillText);
+ skillTextArea.setEditable(false);
+ skillTextArea.setPrefHeight(38.0);
+ skillTextArea.setPrefWidth(290.0);
+ skillTextArea.setStyle("-fx-border-width: 0;");
+ skillTextArea.getStyleClass().add("skill-text");
+
+ skillItem.getChildren().addAll(removeButton, skillTextArea);
+ skillsContainer.getChildren().add(0, skillItem); // Add to the top of the VBox
+ }
+
+ private void handleRemoveSkill(HBox skillItem, int nthSkill) throws IOException {
+ removeSkill(skillItem, nthSkill);
+
+ }
+ private ArrayList getSkills() throws IOException {
+ URL url = new URL("http://localhost:8000/skills/" + LoggedInUser.getId());
+ String response;
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] skills = toStringArray(jsonObject);
+ ArrayList skills1 = new ArrayList<>();
+ for (String t : skills) {
+ JSONObject obj = new JSONObject(t);
+ Skill skill = new Skill(LoggedInUser.getId(), obj.getInt("nthSkill"), obj.getString("text"));
+ skills1.add(skill);
+ }
+ return skills1;
+ }
+ private void removeSkill(HBox skillItem ,int nthSkill) throws IOException {
+ URL url = new URL("http://localhost:8000/skills/" + LoggedInUser.getId() + "/" + nthSkill);
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("DELETE");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+ if (response.equals("successful")) {
+ skillsContainer.getChildren().remove(skillItem);
+ skillCount--;
+ }
+ else {
+ System.out.println(response);
+ }
+
+ }
+ public static String[] toStringArray(JSONArray array) {
+ if(array == null)
+ return new String[0];
+
+ String[] arr = new String[array.length()];
+ for(int i = 0; i < arr.length; i++)
+ arr[i] = array.optString(i);
+ return arr;
+ }
+
+ public void removeSkillBtnClicked(ActionEvent actionEvent) {
+ }
+}
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/User.java b/LinkedInClient/src/main/java/org/example/linkedinclient/User.java
new file mode 100644
index 0000000..60c66b8
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/User.java
@@ -0,0 +1,149 @@
+package org.example.linkedinclient;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class User {
+ @JsonProperty("id")
+ private String id;
+ @JsonProperty("firstName")
+ private String firstName;
+ @JsonProperty("lastName")
+ private String lastName;
+ @JsonProperty("additionalName")
+ private String additionalName;
+ @JsonProperty("country")
+ private String country;
+ @JsonProperty("city")
+ private String city;
+ @JsonProperty("email")
+ private String email;
+ @JsonProperty("password")
+ private String password;
+ @JsonProperty("phoneNumber")
+ private String phoneNumber;
+ @JsonProperty("followers")
+ private int followers;
+ @JsonProperty("followings")
+ private int followings;
+
+ public User(String id, String firstName, String lastName, String additionalName, String country, String city, String email, String password, String phoneNumber, int followers, int followings) {
+ this.id = id;
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.additionalName = additionalName;
+ this.country = country;
+ this.city = city;
+ this.email = email;
+ this.password = password;
+ this.phoneNumber = phoneNumber;
+ this.followers = followers;
+ this.followings = followings;
+ }
+
+ public User() {
+ }
+
+ public int getFollowers() {
+ return followers;
+ }
+
+ public int getFollowings() {
+ return followings;
+ }
+
+ public void setFollowers(int followers) {
+ this.followers = followers;
+ }
+
+ public void setFollowings(int followings) {
+ this.followings = followings;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ 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 getAdditionalName() {
+ return additionalName;
+ }
+
+ public void setAdditionalName(String additionalName) {
+ this.additionalName = additionalName;
+ }
+
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getPhoneNumber() {
+ return phoneNumber;
+ }
+
+ public void setPhoneNumber(String phoneNumber) {
+ this.phoneNumber = phoneNumber;
+ }
+
+ @Override
+ public String toString() {
+ return "User{" +
+ "id='" + id + '\'' +
+ ", firstName='" + firstName + '\'' +
+ ", lastName='" + lastName + '\'' +
+ ", additionalName='" + additionalName + '\'' +
+ ", country='" + country + '\'' +
+ ", city='" + city + '\'' +
+ ", email='" + email + '\'' +
+ ", password='" + password + '\'' +
+ ", phoneNumber='" + phoneNumber + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/UserProfilePageController.java b/LinkedInClient/src/main/java/org/example/linkedinclient/UserProfilePageController.java
new file mode 100644
index 0000000..3d0dede
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/UserProfilePageController.java
@@ -0,0 +1,309 @@
+package org.example.linkedinclient;
+
+import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon;
+import de.jensd.fx.glyphs.fontawesome.FontAwesomeIconView;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.TextArea;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.VBox;
+import javafx.stage.FileChooser;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.example.linkedinclient.FeedController.toStringArray;
+import static org.example.linkedinclient.HelloApplication.LoggedInUser;
+
+public class UserProfilePageController {
+ @FXML
+ private FontAwesomeIconView closeBtn;
+
+ @FXML
+ private VBox educationVBox;
+
+ @FXML
+ private Label emailLabel;
+
+ @FXML
+ private Button followBtn;
+
+ @FXML
+ private Label followersCountLabel;
+
+ @FXML
+ private Label followersLabel;
+
+ @FXML
+ private Label followingsCountLabel;
+
+ @FXML
+ private Label followingsLabel;
+
+ @FXML
+ private Label headlineLabel;
+
+ @FXML
+ private Label nameLabel;
+
+ @FXML
+ private Label phoneLabel;
+
+ @FXML
+ private ImageView profileImageView;
+
+ @FXML
+ private VBox skillsVBox;
+
+ @FXML
+ private TextArea summaryTextArea;
+
+ static User user;
+ static int lastScene;
+
+ @FXML
+ public void initialize() throws IOException {
+ profileImageView.setImage(new Image(downloadImg()));
+ nameLabel.setText(user.getId());
+ headlineLabel.setText(user.getCountry() + ", " + user.getCity());
+ emailLabel.setText(user.getEmail());
+ phoneLabel.setText(user.getPhoneNumber());
+ ArrayList followers = getFollowers();
+ ArrayList followings = getFollowings();
+ followersCountLabel.setText(Integer.toString(followers.size()));
+ followingsCountLabel.setText(Integer.toString(followings.size()));
+ getBio();
+
+ }
+
+ @FXML
+ void OnMouseClickedCloseBtn(MouseEvent event) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(lastScene);
+ }
+
+ private String downloadImg() {
+ if (fileExists("C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\profPic" + user.getId() + ".png"))
+ return "C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\profPic" + user.getId() + ".png";
+ return "C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets\\logo.png";
+ }
+ public static boolean fileExists(String filePath) {
+ File file = new File(filePath);
+ return file.exists() && file.isFile();
+ }
+
+ public void OnMouseClickedShowFollowersBtn(MouseEvent mouseEvent) throws IOException {
+
+ }
+
+ public void OnMouseClickedShowFollowingsBtn(MouseEvent mouseEvent) throws IOException {
+
+ }
+
+ public void OnMouseClickedSumBtn(MouseEvent mouseEvent) {
+ }
+
+ public void OnMouseClickedEduBtn(MouseEvent mouseEvent) throws IOException {
+
+ }
+ public static ArrayList getFollowers() throws IOException {
+ URL url = new URL("http://localhost:8000/follows/followers/" + user.getId());
+ String response;
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] users = toStringArray(jsonObject);
+ ArrayList users1 = new ArrayList<>();
+ for (String t: users) {
+ JSONObject obj = new JSONObject(t);
+ User user = getUser(obj.getString("follower"));
+ users1.add(user);
+ }
+ return users1;
+ }
+ public static User getUser(String userId) throws IOException {
+ String response;
+ URL url = new URL("http://localhost:8000/users/" + userId);
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ responseCode = con.getResponseCode();
+ BufferedReader in1 = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline1;
+ StringBuffer response2 = new StringBuffer();
+ while ((inputline1 = in1.readLine()) != null) {
+ response2.append(inputline1);
+ }
+ in1.close();
+ response = response2.toString();
+ JSONObject obj = new JSONObject(response);
+ User user = new User(userId, obj.getString("firstName"), obj.getString("lastName"), obj.getString("additionalName"), obj.getString("country"), obj.getString("city"), obj.getString("email"), obj.getString("password"), obj.getString("phoneNumber"), obj.getInt("followers"), obj.getInt("followings"));
+ return user;
+ }
+ public static ArrayList getFollowings() throws IOException {
+ URL url = new URL("http://localhost:8000/follows/followings/" + user.getId());
+ String response;
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] users = toStringArray(jsonObject);
+ ArrayList users1 = new ArrayList<>();
+ for (String t: users) {
+ JSONObject obj = new JSONObject(t);
+ User user = getUser(obj.getString("followed"));
+ users1.add(user);
+ }
+ return users1;
+ }
+ private void getBio() throws IOException {
+ String response;
+ URL url = new URL("http://localhost:8000/bios/" + user.getId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ responseCode = con.getResponseCode();
+ BufferedReader in1 = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline1;
+ StringBuffer response2 = new StringBuffer();
+ while ((inputline1 = in1.readLine()) != null) {
+ response2.append(inputline1);
+ }
+ in1.close();
+ response = response2.toString();
+ if (!response.equals("NO BIO!")) {
+ JSONObject obj = new JSONObject(response);
+ summaryTextArea.setText(obj.getString("bioText"));
+ }
+ else
+ summaryTextArea.setText("Add A Summary For YourSelf");
+
+
+ }
+ public void OnMouseClickedSkillBtn(MouseEvent mouseEvent) throws IOException {
+// HelloApplication helloApplication = new HelloApplication();
+// helloApplication.changeScene(9);
+ }
+
+ public void followBtnClicked(ActionEvent actionEvent) throws IOException {
+ if (!isFollowing(LoggedInUser.getId(), user.getId())) {
+ URL url = new URL("http://localhost:8000/follows/" + LoggedInUser.getId() + "/" + user.getId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("POST");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful!")) {
+ followBtn.setText("followed");
+ followBtn.setOnMouseEntered(event -> followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followBtn.setOnMouseExited(event -> followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white;"));
+ followBtn.setStyle("-fx-background-color: green; -fx-text-fill: white;");
+ followersCountLabel.setText(Integer.toString(Integer.parseInt(followersCountLabel.getText()) - 1));
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ else {
+ URL url = new URL("http://localhost:8000/follows/" + LoggedInUser.getId() + "/" + user.getId());
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ con.setRequestMethod("DELETE");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ String response = response1.toString();
+
+ if (response.equals("successful!")) {
+ followBtn.setText("follow");
+ followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;");
+ followBtn.setOnMouseEntered(event -> followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white; -fx-opacity: 0.7;"));
+ followBtn.setOnMouseExited(event -> followBtn.setStyle("-fx-background-color: #0598ff; -fx-text-fill: white;"));
+ followersCountLabel.setText(Integer.toString(Integer.parseInt(followersCountLabel.getText()) - 1));
+ }
+ else {
+ System.out.println(response);
+ }
+ }
+ }
+ private ArrayList getAllFollowings(String userId) throws IOException {
+ String response;
+ URL url = new URL("http://localhost:8000/follows/followings/" + userId);
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ int responseCode = con.getResponseCode();
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputline;
+ StringBuffer response1 = new StringBuffer();
+ while ((inputline = in.readLine()) != null) {
+ response1.append(inputline);
+ }
+ in.close();
+ response = response1.toString();
+ JSONArray jsonObject = new JSONArray(response);
+ String[] follows = toStringArray(jsonObject);
+ ArrayList followings = new ArrayList<>();
+ for (String t: follows) {
+ JSONObject obj = new JSONObject(t);
+ Follow l = new Follow(obj.getString("follower"), obj.getString("followed"));
+ followings.add(l);
+ }
+ return followings;
+ }
+ private boolean isFollowing(String follower, String followed) throws IOException {
+ ArrayList followings = getAllFollowings(follower);
+ for (Follow t: followings) {
+ if (t.getFollowed().equals(followed) && t.getFollower().equals(follower))
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/LinkedInClient/src/main/java/org/example/linkedinclient/sumPageController.java b/LinkedInClient/src/main/java/org/example/linkedinclient/sumPageController.java
new file mode 100644
index 0000000..aef517f
--- /dev/null
+++ b/LinkedInClient/src/main/java/org/example/linkedinclient/sumPageController.java
@@ -0,0 +1,69 @@
+package org.example.linkedinclient;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import javafx.event.ActionEvent;
+import javafx.fxml.FXML;
+import javafx.scene.control.Button;
+import javafx.scene.control.TextArea;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+import static org.example.linkedinclient.HelloApplication.LoggedInUser;
+
+public class sumPageController {
+ @FXML
+ private Button cancelBtn;
+
+ @FXML
+ private Button saveBtn;
+
+ @FXML
+ private TextArea summaryTextArea;
+ public void handleCancel(ActionEvent actionEvent) throws IOException {
+ HelloApplication helloApplication = new HelloApplication();
+ summaryTextArea.setText("");
+ helloApplication.changeScene(5);
+ }
+ private void saveBio() throws IOException {
+ String response;
+ URL url = new URL("http://localhost:8000/bios");
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("JWT", HelloApplication.token);
+ Bio bio = new Bio(LoggedInUser.getId(), summaryTextArea.getText(), "");
+ ObjectMapper objectMapper = new ObjectMapper();
+ String json = objectMapper.writeValueAsString(bio);
+
+ byte[] postDataBytes = json.getBytes();
+
+ con.setRequestMethod("POST");
+ con.setDoOutput(true);
+ con.getOutputStream().write(postDataBytes);
+
+ try (Reader in = new BufferedReader(new InputStreamReader(con.getInputStream()))) {
+ StringBuilder sb = new StringBuilder();
+ for (int c; (c = in.read()) > 0; ) {
+ sb.append((char) c);
+ }
+ response = sb.toString();
+ }
+
+ if (response.equals("successful!")) {
+ HelloApplication helloApplication = new HelloApplication();
+ helloApplication.changeScene(5);
+ } else {
+ System.out.println("Server response: " + response);
+ }
+ }
+
+ public void handleSave(ActionEvent actionEvent) throws IOException {
+ saveBio();
+ }
+}
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/LinkedInFeed.fxml b/LinkedInClient/src/main/resources/org/example/linkedinclient/LinkedInFeed.fxml
new file mode 100644
index 0000000..636199f
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/LinkedInFeed.fxml
@@ -0,0 +1,224 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/logo.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/logo.png
new file mode 100644
index 0000000..08aabe0
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/logo.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicadnan__h20051720022507997.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicadnan__h20051720022507997.png
new file mode 100644
index 0000000..812be03
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicadnan__h20051720022507997.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicadnan__h20051720022548619.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicadnan__h20051720022548619.png
new file mode 100644
index 0000000..812be03
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicadnan__h20051720022548619.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicadnan__h20051720022872479.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicadnan__h20051720022872479.png
new file mode 100644
index 0000000..65102cd
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicadnan__h20051720022872479.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicadnan__h20051720117178854.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicadnan__h20051720117178854.png
new file mode 100644
index 0000000..69ede3c
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicadnan__h20051720117178854.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicadnan__h20051720117186200.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicadnan__h20051720117186200.png
new file mode 100644
index 0000000..69ede3c
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicadnan__h20051720117186200.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicarianEbi20051720018968067.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicarianEbi20051720018968067.png
new file mode 100644
index 0000000..f2e7000
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicarianEbi20051720018968067.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicarianEbi20051720022071048.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicarianEbi20051720022071048.png
new file mode 100644
index 0000000..1417ca5
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicarianEbi20051720022071048.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicarianEbi20051720022318800.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicarianEbi20051720022318800.png
new file mode 100644
index 0000000..1417ca5
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicarianEbi20051720022318800.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicrosieNaz1720106168923.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicrosieNaz1720106168923.png
new file mode 100644
index 0000000..326cad2
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicrosieNaz1720106168923.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicsadraZia2221720018586100.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicsadraZia2221720018586100.png
new file mode 100644
index 0000000..7df7e5e
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicsadraZia2221720018586100.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicsadraZia2221720026061580.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicsadraZia2221720026061580.png
new file mode 100644
index 0000000..dd42e0d
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicsadraZia2221720026061580.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicsinaRiot1720001083765.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicsinaRiot1720001083765.png
new file mode 100644
index 0000000..08aabe0
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicsinaRiot1720001083765.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicsuccessful!.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicsuccessful!.png
new file mode 100644
index 0000000..dd42e0d
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/postPicsuccessful!.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicadnan__h2005.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicadnan__h2005.png
new file mode 100644
index 0000000..d766745
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicadnan__h2005.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicarianEbi2005.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicarianEbi2005.png
new file mode 100644
index 0000000..3cc2681
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicarianEbi2005.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicrosieNaz.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicrosieNaz.png
new file mode 100644
index 0000000..69ede3c
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicrosieNaz.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicsadraZia222.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicsadraZia222.png
new file mode 100644
index 0000000..c8e6ba5
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicsadraZia222.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicshayanShah.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicshayanShah.png
new file mode 100644
index 0000000..7df7e5e
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicshayanShah.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicsinaRiot.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicsinaRiot.png
new file mode 100644
index 0000000..1417ca5
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/assets/profPicsinaRiot.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/commentSection.fxml b/LinkedInClient/src/main/resources/org/example/linkedinclient/commentSection.fxml
new file mode 100644
index 0000000..da7e694
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/commentSection.fxml
@@ -0,0 +1,207 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/educationComponent.fxml b/LinkedInClient/src/main/resources/org/example/linkedinclient/educationComponent.fxml
new file mode 100644
index 0000000..434dd01
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/educationComponent.fxml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/educationsView.fxml b/LinkedInClient/src/main/resources/org/example/linkedinclient/educationsView.fxml
new file mode 100644
index 0000000..9f27e71
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/educationsView.fxml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/followersPage.fxml b/LinkedInClient/src/main/resources/org/example/linkedinclient/followersPage.fxml
new file mode 100644
index 0000000..ff5d2cf
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/followersPage.fxml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/followingsPage.fxml b/LinkedInClient/src/main/resources/org/example/linkedinclient/followingsPage.fxml
new file mode 100644
index 0000000..16e717f
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/followingsPage.fxml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/img/linkedin.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/img/linkedin.png
new file mode 100644
index 0000000..326cad2
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/img/linkedin.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/img/logo.png b/LinkedInClient/src/main/resources/org/example/linkedinclient/img/logo.png
new file mode 100644
index 0000000..08aabe0
Binary files /dev/null and b/LinkedInClient/src/main/resources/org/example/linkedinclient/img/logo.png differ
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/login.fxml b/LinkedInClient/src/main/resources/org/example/linkedinclient/login.fxml
new file mode 100644
index 0000000..b2daae4
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/login.fxml
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/profileView.fxml b/LinkedInClient/src/main/resources/org/example/linkedinclient/profileView.fxml
new file mode 100644
index 0000000..94c721f
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/profileView.fxml
@@ -0,0 +1,219 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/signIn.fxml b/LinkedInClient/src/main/resources/org/example/linkedinclient/signIn.fxml
new file mode 100644
index 0000000..5b1a020
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/signIn.fxml
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/skillComponent.fxml b/LinkedInClient/src/main/resources/org/example/linkedinclient/skillComponent.fxml
new file mode 100644
index 0000000..ce16513
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/skillComponent.fxml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/skillPage.fxml b/LinkedInClient/src/main/resources/org/example/linkedinclient/skillPage.fxml
new file mode 100644
index 0000000..0cf3591
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/skillPage.fxml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/styleAddEducationForm.css b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleAddEducationForm.css
new file mode 100644
index 0000000..7efc18b
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleAddEducationForm.css
@@ -0,0 +1,56 @@
+.root {
+ -fx-background-color: #f8f9fa;
+ -fx-font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
+}
+
+.form-title {
+ -fx-font-size: 24px;
+ -fx-font-weight: bold;
+ -fx-text-fill: #343a40;
+}
+
+.input-label {
+ -fx-font-size: 14px;
+ -fx-font-weight: bold;
+ -fx-text-fill: #495057;
+}
+
+.input-field {
+ -fx-padding: 10px;
+ -fx-border-color: #ced4da;
+ -fx-border-radius: 5px;
+ -fx-background-radius: 5px;
+ -fx-background-color: #fff;
+ -fx-font-size: 14px;
+}
+
+.input-field:focused {
+ -fx-border-color: #007bff;
+ -fx-box-shadow: 0 0 5px rgba(0, 123, 255, 0.5);
+}
+
+.save-button {
+ -fx-background-color: #007bff;
+ -fx-text-fill: #fff;
+ -fx-font-size: 14px;
+ -fx-padding: 10px 20px;
+ -fx-border-radius: 5px;
+ -fx-background-radius: 5px;
+}
+
+.save-button:hover {
+ -fx-background-color: #0056b3;
+}
+
+.cancel-button {
+ -fx-background-color: #6c757d;
+ -fx-text-fill: #fff;
+ -fx-font-size: 14px;
+ -fx-padding: 10px 20px;
+ -fx-border-radius: 5px;
+ -fx-background-radius: 5px;
+}
+
+.cancel-button:hover {
+ -fx-background-color: #5a6268;
+}
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/styleAddSkillForm.css b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleAddSkillForm.css
new file mode 100644
index 0000000..99e5d72
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleAddSkillForm.css
@@ -0,0 +1,65 @@
+/* Style for the root AnchorPane */
+.root {
+ -fx-background-color: #f3f2ef;
+ -fx-padding: 20;
+}
+
+/* Style for the title label */
+.form-title {
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 24px;
+ -fx-font-weight: bold;
+ -fx-text-fill: #333;
+}
+
+/* Style for the input labels */
+.input-label {
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 14px;
+ -fx-text-fill: #333;
+}
+
+/* Style for the input fields */
+.input-field {
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 14px;
+ -fx-background-color: #fff;
+ -fx-border-color: #d1d1d1;
+ -fx-border-radius: 5;
+ -fx-background-radius: 5;
+ -fx-padding: 10;
+}
+
+/* Style for the buttons */
+.cancel-button {
+ -fx-background-color: #d9534f;
+ -fx-text-fill: white;
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 14px;
+ -fx-background-radius: 5;
+ -fx-padding: 10 20;
+}
+
+.cancel-button:hover {
+ -fx-background-color: #c9302c;
+}
+
+.save-button {
+ -fx-background-color: #28a745;
+ -fx-text-fill: white;
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 14px;
+ -fx-background-radius: 5;
+ -fx-padding: 10 20;
+}
+
+.save-button:hover {
+ -fx-background-color: #218838;
+}
+
+/* Style for the error label */
+#errorLabel {
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 14px;
+ -fx-text-fill: red;
+}
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/styleComment.css b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleComment.css
new file mode 100644
index 0000000..3bff1fa
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleComment.css
@@ -0,0 +1,120 @@
+.post-box {
+ -fx-background-color: white;
+ -fx-border-color: lightgray;
+ -fx-border-width: 1px;
+ -fx-padding: 20px;
+ -fx-spacing: 10px;
+ -fx-background-radius: 10px;
+ -fx-border-radius: 10px;
+}
+.post-box-btn {
+ -fx-background-color: transparent;
+ -fx-border-radius: 5px;
+ -fx-background-radius: 5px;
+ -fx-text-fill: #333;
+ -fx-padding: 5px 15px;
+ -fx-cursor: hand;
+ -fx-transition: background-color 2s;
+}
+.post-header {
+ -fx-font-weight: bold;
+ -fx-font-size: 16px;
+ -fx-text-fill: #333;
+}
+
+.post-text-area {
+ -fx-background-color: #f9f9f9;
+ -fx-border-color: lightgray;
+ -fx-border-radius: 15px;
+ -fx-background-radius: 15px;
+ -fx-padding: 10px;
+ -fx-font-size: 14px;
+ -fx-prompt-text-fill: #ccc;
+ -fx-text-fill: #333;
+ -fx-border-width: 1px;
+}
+
+.post-text-area:focus {
+ -fx-border-color: #0598ff;
+}
+
+.post-button {
+ -fx-background-color: #e6e6f7;
+ -fx-border-radius: 5px;
+ -fx-background-radius: 5px;
+ -fx-text-fill: #333;
+ -fx-padding: 5px 15px;
+ -fx-cursor: hand;
+ -fx-transition: background-color 2s;
+}
+
+.post-button:hover {
+ -fx-background-color: #ccc;
+}
+
+.logo {
+ /* Style for logo */
+ -fx-text-fill: #0598ff;
+}
+
+.post-container {
+ /* Style for post container */
+ -fx-background-color: #ffffff;
+ -fx-border-color: #dddddd;
+ -fx-border-radius: 5;
+ -fx-background-radius: 5;
+ -fx-padding: 10;
+ -fx-spacing: 10;
+}
+
+.post-content {
+ /* Style for post content */
+ -fx-font-size: 14px;
+}
+
+.comment-count {
+ /* Style for comment count */
+ -fx-font-size: 12px;
+ -fx-text-fill: #666666;
+}
+
+.comment-container {
+ /* Style for comment container */
+ -fx-padding: 10;
+ -fx-spacing: 10;
+}
+
+.comment-scrollpane {
+ /* Style for comment scroll pane */
+ -fx-background-color: transparent;
+ -fx-border-width: 0;
+ -fx-padding: 0;
+}
+
+.comments-box {
+ /* Style for comments box inside scroll pane */
+ -fx-spacing: 10;
+ -fx-padding: 10;
+}
+
+.likeBtn {
+ -fx-text-fill: #0580ff;
+}
+.thumbIcon {
+ -fx-fill: #0580ff;
+}
+.cmtBtn {
+ -fx-text-fill: #2dcf89;
+}
+.commentIcon {
+ -fx-fill: #2dcf89;
+}
+.shareBtn {
+ -fx-text-fill: #e33b6b;
+}
+.shareIcon {
+ -fx-fill: #e33b6b;
+}
+.post-box-btn:hover {
+ -fx-background-color: #ccc;
+}
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/styleFeed.css b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleFeed.css
new file mode 100644
index 0000000..32d6747
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleFeed.css
@@ -0,0 +1,183 @@
+.top-bar {
+ -fx-background-color: #0598ff;
+ -fx-padding: 10;
+ -fx-alignment: center;
+}
+
+.nav-button {
+ -fx-background-color: transparent;
+ -fx-text-fill: black;
+ -fx-font-size: 16px;
+ -fx-border-width: 0 0 3px 0;
+ -fx-transition: all 1s;
+}
+
+.nav-button:hover {
+ -fx-background-color: #e0e0e0;
+}
+
+.sidebar {
+ -fx-padding: 10;
+ -fx-background-color: #f4f4f4;
+}
+
+.sidebar-header {
+ -fx-font-weight: bold;
+ -fx-font-size: 16px;
+ -fx-text-fill: #333;
+}
+
+.sidebar-item {
+ -fx-font-size: 14px;
+ -fx-text-fill: #666;
+}
+
+.post-box {
+ -fx-background-color: white;
+ -fx-border-color: lightgray;
+ -fx-border-width: 1px;
+ -fx-padding: 20px;
+ -fx-spacing: 10px;
+ -fx-background-radius: 10px;
+ -fx-border-radius: 10px;
+}
+.post-box-btn {
+ -fx-background-color: transparent;
+ -fx-border-radius: 5px;
+ -fx-background-radius: 5px;
+ -fx-text-fill: #333;
+ -fx-padding: 5px 15px;
+ -fx-cursor: hand;
+ -fx-transition: background-color 2s;
+}
+.likeBtn {
+ -fx-text-fill: #0580ff;
+}
+.thumbIcon {
+ -fx-fill: #0580ff;
+}
+.cmtBtn {
+ -fx-text-fill: #2dcf89;
+}
+.commentIcon {
+ -fx-fill: #2dcf89;
+}
+.shareBtn {
+ -fx-text-fill: #e33b6b;
+}
+.shareIcon {
+ -fx-fill: #e33b6b;
+}
+.post-box-btn:hover {
+ -fx-background-color: #ccc;
+}
+
+.post-header {
+ -fx-font-weight: bold;
+ -fx-font-size: 16px;
+ -fx-text-fill: #333;
+}
+
+.post-text-area {
+ -fx-background-color: #f9f9f9;
+ -fx-border-color: lightgray;
+ -fx-border-radius: 15px;
+ -fx-background-radius: 15px;
+ -fx-padding: 10px;
+ -fx-font-size: 14px;
+ -fx-prompt-text-fill: #ccc;
+ -fx-text-fill: #333;
+ -fx-border-width: 1px;
+}
+
+.post-text-area:focus {
+ -fx-border-color: #0598ff;
+}
+
+.post-button {
+ -fx-background-color: #e6e6f7;
+ -fx-border-radius: 5px;
+ -fx-background-radius: 5px;
+ -fx-text-fill: #333;
+ -fx-padding: 5px 15px;
+ -fx-cursor: hand;
+ -fx-transition: background-color 2s;
+}
+
+.post-button:hover {
+ -fx-background-color: #ccc;
+}
+
+/* Sidebar */
+.sidebar {
+ -fx-padding: 20px;
+ -fx-spacing: 15px;
+ -fx-background-color: #f3f2ef;
+ -fx-border-width: 0 1px 0 0;
+ -fx-border-color: #ddd;
+}
+
+/* Sidebar */
+.sidebar {
+ -fx-padding: 20px;
+ -fx-spacing: 15px;
+ -fx-background-color: #f3f2ef;
+ -fx-border-width: 0 1px 0 0;
+ -fx-border-color: #ddd;
+}
+
+/* Profile Section */
+.profile-pane {
+ -fx-alignment: center;
+ -fx-padding: 10px 0;
+}
+
+.profile-name {
+ -fx-font-size: 14px;
+ -fx-font-weight: bold;
+ -fx-text-fill: #333;
+}
+
+.profile-title {
+ -fx-font-size: 12px;
+ -fx-text-fill: #777;
+}
+
+/* Sidebar Items */
+.sidebar-items {
+ -fx-spacing: 10px;
+}
+
+/* Sidebar item HBox */
+.sidebar-item {
+ -fx-padding: 10px 15px;
+ -fx-alignment: center-left;
+ -fx-cursor: hand;
+ -fx-background-color: transparent;
+ -fx-border-radius: 5px;
+ -fx-transition: background-color 0.3s;
+}
+
+.sidebar-item:hover {
+ -fx-background-color: #e1e9ed;
+}
+
+.sidebar-item > .font-icon {
+ -fx-fill: #333;
+ -fx-font-size: 16px;
+}
+
+.sidebar-item > Label {
+ -fx-text-fill: #333;
+ -fx-font-size: 14px;
+}
+
+.post-text-area {
+ -fx-background-radius: 10;
+ -fx-padding: 10;
+}
+.scroll-pane-label {
+ -fx-background-color: transparent;
+ -fx-border-width: 0 0 0 0;
+}
+
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/styleFollowersPage.css b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleFollowersPage.css
new file mode 100644
index 0000000..da32428
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleFollowersPage.css
@@ -0,0 +1,29 @@
+/* Style for the root AnchorPane */
+.root {
+ -fx-background-color: #f3f2ef;
+ -fx-padding: 20;
+}
+
+/* Style for the page title */
+.page-title {
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 24px;
+ -fx-font-weight: bold;
+ -fx-text-fill: #333;
+}
+
+/* Style for the followers container */
+.followers-container {
+ -fx-background-color: #fff;
+ -fx-padding: 10;
+ -fx-border-radius: 5;
+ -fx-background-radius: 5;
+ -fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.1), 10, 0, 0, 0);
+}
+
+/* Style for the followers scroll pane */
+.followers-scroll-pane {
+ -fx-background-color: transparent;
+ -fx-padding: 10;
+ -fx-border-radius: 5;
+}
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/styleProfileView.css b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleProfileView.css
new file mode 100644
index 0000000..3c939ba
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleProfileView.css
@@ -0,0 +1,69 @@
+/* General Styles */
+.profile-image-pane {
+ -fx-border-radius: 50%;
+ -fx-background-radius: 50%;
+ -fx-padding: 10;
+}
+
+.profile-image {
+ -fx-clip: circle(60px at 60px 60px);
+}
+
+.change-photo-button {
+ -fx-background-color: #0073b1;
+ -fx-text-fill: white;
+ -fx-background-radius: 5;
+ -fx-padding: 5 10;
+ -fx-font-size: 12px;
+}
+
+.name-label {
+ -fx-font-size: 24px;
+ -fx-font-weight: bold;
+}
+
+.headline-label {
+ -fx-font-size: 16px;
+ -fx-text-fill: #666666;
+}
+
+.info-label {
+ -fx-font-weight: bold;
+}
+
+.info-text {
+ -fx-text-fill: #666666;
+}
+
+.custom-titled-pane > .title {
+ -fx-background-color: #f3f3f3;
+ -fx-border-color: transparent;
+ -fx-padding: 10;
+}
+
+.custom-titled-pane > .content {
+ -fx-padding: 10;
+}
+
+.edit-icon {
+ -fx-fill: #0073b1;
+ -fx-cursor: hand;
+}
+
+VBox {
+ -fx-spacing: 10;
+ -fx-padding: 20;
+ -fx-background-color: #ffffff;
+ -fx-border-color: #e1e1e1;
+ -fx-border-width: 1;
+ -fx-border-radius: 5;
+ -fx-background-radius: 5;
+}
+
+HBox {
+ -fx-spacing: 10;
+ -fx-padding: 10;
+}
+.logOutBtn: hover {
+ -fx-opacity: 0.6;
+}
\ No newline at end of file
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/styleSkillView.css b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleSkillView.css
new file mode 100644
index 0000000..c50aedb
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleSkillView.css
@@ -0,0 +1,89 @@
+/* Style for the root AnchorPane */
+.root {
+ -fx-background-color: #f3f2ef;
+ -fx-padding: 20;
+}
+
+/* Style for the title label */
+.title-label {
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 24px;
+ -fx-font-weight: bold;
+ -fx-text-fill: #333;
+}
+
+/* Style for the skills scroll pane */
+.skills-scroll-pane {
+ -fx-background-color: transparent;
+ -fx-border-color: transparent;
+}
+
+/* Style for the VBox containing skills */
+.skills-container {
+ -fx-background-color: #fff;
+ -fx-padding: 10;
+ -fx-border-color: #d1d1d1;
+ -fx-border-radius: 5;
+ -fx-background-radius: 5;
+}
+
+/* Style for each skill item */
+.skill-item {
+ -fx-background-color: #e1e1e1;
+ -fx-padding: 10;
+ -fx-border-color: #ccc;
+ -fx-border-radius: 5;
+ -fx-background-radius: 5;
+ -fx-alignment: CENTER_LEFT;
+ -fx-spacing: 10;
+}
+
+/* Style for the skill text */
+.skill-text {
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 14px;
+ -fx-text-fill: #333;
+}
+
+/* Style for the order number */
+.skill-number {
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 14px;
+ -fx-text-fill: #666;
+}
+
+/* Style for the remove button */
+.remove-button {
+ -fx-background-color: #ff6b6b;
+ -fx-text-fill: white;
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 14px;
+ -fx-background-radius: 5;
+ -fx-padding: 5 10;
+}
+
+/* Style for the add skill button */
+.add-skill-button {
+ -fx-background-color: #28a745;
+ -fx-text-fill: white;
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 14px;
+ -fx-background-radius: 5;
+ -fx-padding: 10 20;
+}
+
+.add-skill-button:hover {
+ -fx-background-color: #218838;
+}
+
+/* Style for the close button */
+#closeBtn {
+ -fx-background-color: transparent;
+ -fx-text-fill: #333;
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 18px;
+}
+
+#closeBtn:hover {
+ -fx-text-fill: #ff6b6b;
+}
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/styleSummaryForm.css b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleSummaryForm.css
new file mode 100644
index 0000000..3a3e533
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/styleSummaryForm.css
@@ -0,0 +1,63 @@
+/* Apply this style to the VBox */
+.root {
+ -fx-background-color: #f3f2ef;
+ -fx-padding: 20;
+}
+
+/* Style for the form title */
+.form-title {
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 24px;
+ -fx-font-weight: bold;
+ -fx-text-fill: #333;
+}
+
+/* Style for input labels */
+.input-label {
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 14px;
+ -fx-text-fill: #666;
+}
+
+/* Style for TextArea */
+.input-field {
+ -fx-background-color: white;
+ -fx-border-color: #d1d1d1;
+ -fx-border-radius: 5;
+ -fx-background-radius: 5;
+ -fx-padding: 10;
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 14px;
+}
+
+.input-field:focused {
+ -fx-border-color: #0073b1;
+ -fx-box-shadow: 0 0 5px rgba(0, 115, 177, 0.5);
+}
+
+/* Style for buttons */
+.cancel-button {
+ -fx-background-color: #d1d1d1;
+ -fx-text-fill: white;
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 14px;
+ -fx-background-radius: 5;
+ -fx-padding: 10 20;
+}
+
+.cancel-button:hover {
+ -fx-background-color: #b0b0b0;
+}
+
+.save-button {
+ -fx-background-color: #0073b1;
+ -fx-text-fill: white;
+ -fx-font-family: 'Segoe UI', sans-serif;
+ -fx-font-size: 14px;
+ -fx-background-radius: 5;
+ -fx-padding: 10 20;
+}
+
+.save-button:hover {
+ -fx-background-color: #005f8d;
+}
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/sumPage.fxml b/LinkedInClient/src/main/resources/org/example/linkedinclient/sumPage.fxml
new file mode 100644
index 0000000..97162ca
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/sumPage.fxml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LinkedInClient/src/main/resources/org/example/linkedinclient/userProfilePage.fxml b/LinkedInClient/src/main/resources/org/example/linkedinclient/userProfilePage.fxml
new file mode 100644
index 0000000..7e4df6b
--- /dev/null
+++ b/LinkedInClient/src/main/resources/org/example/linkedinclient/userProfilePage.fxml
@@ -0,0 +1,192 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/adnan/server/assets/logo.png b/src/main/java/com/adnan/server/assets/logo.png
new file mode 100644
index 0000000..08aabe0
Binary files /dev/null and b/src/main/java/com/adnan/server/assets/logo.png differ
diff --git a/src/main/java/com/adnan/server/controllers/HashtagController.java b/src/main/java/com/adnan/server/controllers/HashtagController.java
new file mode 100644
index 0000000..2b826e5
--- /dev/null
+++ b/src/main/java/com/adnan/server/controllers/HashtagController.java
@@ -0,0 +1,75 @@
+package com.adnan.server.controllers;
+
+import com.adnan.server.dataAccess.*;
+import com.adnan.server.models.Content;
+import com.adnan.server.models.Hashtag;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+
+public class HashtagController {
+ private static PostDataAccess PDA = null;
+ private static CommentDataAccess COMDA = null;
+ private static HashtagDataAccess HDA = null;
+ private static LoggedInUserDataAccess LIUDA = null;
+
+ public HashtagController() throws SQLException {
+ PDA = new PostDataAccess();
+ COMDA = new CommentDataAccess();
+ HDA = new HashtagDataAccess();
+ LIUDA = new LoggedInUserDataAccess();
+ }
+
+ public String addHashtag(String id, String contentId) throws SQLException {
+ if (!PDA.postExists(contentId) && !COMDA.commentExists(contentId))
+ return "POST OR COMMENT NOT FOUND!!!";
+ Content content;
+ if (PDA.postExists(contentId)) {
+ content = PDA.getPost(contentId);
+ if (!LIUDA.getUser().equals(content.getPosterId()))
+ return "NOT ALLOWED!!!";
+ if (HDA.tagExists(id, contentId))
+ return "ALREADY EXISTS IN THIS CONTENT!!";
+ Hashtag hashtag = new Hashtag(id, contentId);
+ HDA.addHashtag(hashtag);
+ }
+ else {
+ content = COMDA.getComment(contentId);
+ if (!LIUDA.getUser().equals(content.getPosterId()))
+ return "NOT ALLOWED!!!";
+ if (HDA.tagExists(id, contentId))
+ return "ALREADY EXISTS IN THIS CONTENT!!";
+ Hashtag hashtag = new Hashtag(id, contentId);
+ HDA.addHashtag(hashtag);
+ }
+ return "successful";
+ }
+ public String deleteHashtag(String id, String contentId) throws SQLException {
+ if (!PDA.postExists(contentId) && !COMDA.commentExists(contentId))
+ return "POST OR COMMENT NOT FOUND!!!";
+ Content content;
+ if (PDA.postExists(contentId)) {
+ content = PDA.getPost(contentId);
+ if (!LIUDA.getUser().equals(content.getPosterId()))
+ return "NOT ALLOWED!!!";
+ Hashtag hashtag = new Hashtag(id, contentId);
+ HDA.deleteHashtag(hashtag);
+ }
+ else {
+ content = COMDA.getComment(contentId);
+ if (!LIUDA.getUser().equals(content.getPosterId()))
+ return "NOT ALLOWED!!!";
+ Hashtag hashtag = new Hashtag(id, contentId);
+ HDA.deleteHashtag(hashtag);
+ }
+ return "successful";
+ }
+ public String getContents(String id) throws SQLException, JsonProcessingException {
+ ArrayList contents = HDA.getHashtag(id);
+ if (contents == null) return "NO POST FOUND!!!";
+ ObjectMapper objectMapper = new ObjectMapper();
+ return objectMapper.writeValueAsString(contents);
+ }
+}
diff --git a/src/main/java/com/adnan/server/controllers/LikeController.java b/src/main/java/com/adnan/server/controllers/LikeController.java
index 909da14..937fe67 100644
--- a/src/main/java/com/adnan/server/controllers/LikeController.java
+++ b/src/main/java/com/adnan/server/controllers/LikeController.java
@@ -26,6 +26,7 @@ public LikeController() throws SQLException {
COMDA = new CommentDataAccess();
}
public String addLike(String liker, String liked) throws SQLException {
+ System.out.println(liker + " " + liked);
if (!UDA.userExists(liker) || (!PDA.postExists(liked) && !COMDA.commentExists(liked)))
return "USER OR POST NOT FOUND!!";
if (!LIUDA.getUser().equals(liker))
diff --git a/src/main/java/com/adnan/server/controllers/PostController.java b/src/main/java/com/adnan/server/controllers/PostController.java
index 0760698..358d68b 100644
--- a/src/main/java/com/adnan/server/controllers/PostController.java
+++ b/src/main/java/com/adnan/server/controllers/PostController.java
@@ -1,9 +1,6 @@
package com.adnan.server.controllers;
-import com.adnan.server.dataAccess.CommentDataAccess;
-import com.adnan.server.dataAccess.LoggedInUserDataAccess;
-import com.adnan.server.dataAccess.PostDataAccess;
-import com.adnan.server.dataAccess.UserDataAccess;
+import com.adnan.server.dataAccess.*;
import com.adnan.server.models.Comment;
import com.adnan.server.models.Content;
import com.adnan.server.models.Post;
@@ -42,7 +39,7 @@ public String createPost(String posterId, String content) throws SQLException {
return "USER NOT FOUND!!!";
Post post = new Post(posterId, content);
PDA.addPost(post);
- return "successful!";
+ return post.getPostId();
}
public String updatePost(String postId, String posterId, String content) throws SQLException {
if (!PDA.postExists(postId) || !UDA.userExists(posterId))
@@ -76,7 +73,7 @@ public String addComment(String posterId, String content, String parentId) throw
COMDA.updateComment((Comment) post);
}
COMDA.addComment(comment);
- return "successful";
+ return comment.getPostId();
}
public String deleteComment(String postId) throws SQLException {
if (!COMDA.commentExists(postId))
@@ -85,6 +82,7 @@ public String deleteComment(String postId) throws SQLException {
if (!comment.getPosterId().equals(LIUDA.getUser()))
return "NOT ALLOWED!!!";
Content post;
+
if (PDA.postExists((comment.getParentId()))) {
post = PDA.getPost(comment.getParentId());
post.decreaseComment();
diff --git a/src/main/java/com/adnan/server/controllers/SkillController.java b/src/main/java/com/adnan/server/controllers/SkillController.java
index 905d72d..5c565cd 100644
--- a/src/main/java/com/adnan/server/controllers/SkillController.java
+++ b/src/main/java/com/adnan/server/controllers/SkillController.java
@@ -22,8 +22,23 @@ public String createSkill(String userId, String text) throws SQLException {
if(SDA.countSkills(userId) == 5)
return "YOU CAN ONLY ADD 5 SKILLS!!!";
int a = SDA.countSkills(userId);
- Skill skill = new Skill(userId, ++a, text);
- SDA.addSkill(skill);
+ ArrayList skills = SDA.getSkills(userId);
+ Skill skill;
+ int x = 1;
+ if (a != 0) {
+ for (int i = 0; i < a ; i++) {
+ if (skills.get(i).getNthSkill() != x) {
+ a = x - 1;
+ break;
+ }
+ x++;
+ }
+ skill = new Skill(userId, ++a, text);
+ }
+ else {
+ skill = new Skill(userId, ++a, text);
+ }
+ SDA.addSkill(skill);
return "successful";
}
public String getSkills(String userId) throws SQLException, JsonProcessingException {
diff --git a/src/main/java/com/adnan/server/controllers/UserController.java b/src/main/java/com/adnan/server/controllers/UserController.java
index a83460c..97ca837 100644
--- a/src/main/java/com/adnan/server/controllers/UserController.java
+++ b/src/main/java/com/adnan/server/controllers/UserController.java
@@ -97,5 +97,9 @@ public String deleteBio(String userId) throws SQLException {
else
return "NO BIO FOUND!";
}
+ public boolean userExists(String id) throws SQLException {
+ return UDA.userExists(id);
+ }
+
}
diff --git a/src/main/java/com/adnan/server/dataAccess/CommentDataAccess.java b/src/main/java/com/adnan/server/dataAccess/CommentDataAccess.java
index 993fd5f..b36d33a 100644
--- a/src/main/java/com/adnan/server/dataAccess/CommentDataAccess.java
+++ b/src/main/java/com/adnan/server/dataAccess/CommentDataAccess.java
@@ -58,12 +58,13 @@ public ArrayList getComments() throws SQLException {
return posts;
}
public Comment getComment(String postId) throws SQLException {
- PreparedStatement statement = connection.prepareStatement("SELECT * FROM comments where postId = ?");
+ PreparedStatement statement = connection.prepareStatement("SELECT * FROM comments WHERE postId = ?");
statement.setString(1, postId);
ResultSet resultSet = statement.executeQuery();
if (resultSet.next()) {
Comment comment = new Comment();
comment.setPostId(postId);
+ comment.setPosterId(resultSet.getString("posterId"));
comment.setContent(resultSet.getString("content"));
comment.setCommentsNumber(resultSet.getInt("commentsNumber"));
comment.setLikesNumber(resultSet.getInt("likesNumber"));
diff --git a/src/main/java/com/adnan/server/dataAccess/HashtagDataAccess.java b/src/main/java/com/adnan/server/dataAccess/HashtagDataAccess.java
new file mode 100644
index 0000000..8d3db39
--- /dev/null
+++ b/src/main/java/com/adnan/server/dataAccess/HashtagDataAccess.java
@@ -0,0 +1,57 @@
+package com.adnan.server.dataAccess;
+
+import com.adnan.server.models.Hashtag;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+
+public class HashtagDataAccess {
+ private final Connection connection;
+ public HashtagDataAccess() throws SQLException {
+ connection = MainDataBase.getConnection();
+ }
+
+ public void addHashtag(Hashtag hashtag) throws SQLException {
+ PreparedStatement statement = connection.prepareStatement("INSERT INTO tags (id, contentId) VALUES (?,?)");
+ statement.setString(1, hashtag.getId());
+ statement.setString(2, hashtag.getContentId());
+ statement.executeUpdate();
+ }
+ public void deleteHashtag(Hashtag hashtag) throws SQLException {
+ PreparedStatement statement = connection.prepareStatement("DELETE FROM tags WHERE id = ? AND contentId = ?");
+ statement.setString(1, hashtag.getId());
+ statement.setString(2, hashtag.getContentId());
+ statement.executeUpdate();
+ }
+ public ArrayList getHashtag(String id) throws SQLException {
+ PreparedStatement statement = connection.prepareStatement("SELECT * FROM tags WHERE id = ?");
+ statement.setString(1, id);
+ ResultSet resultSet = statement.executeQuery();
+ ArrayList contents = new ArrayList<>();
+ while (resultSet.next()) {
+ contents.add(resultSet.getString("contentId"));
+ }
+ return contents;
+ }
+
+ public ArrayList getTags(String contentId) throws SQLException {
+ PreparedStatement statement = connection.prepareStatement("SELECT id FROM tags WHERE contentId = ?");
+ statement.setString(1, contentId);
+ ResultSet resultSet = statement.executeQuery();
+ ArrayList tags = new ArrayList<>();
+ while (resultSet.next()) {
+ tags.add(resultSet.getString("id"));
+ }
+ return tags;
+ }
+ public boolean tagExists(String id, String contentId) throws SQLException {
+ PreparedStatement statement = connection.prepareStatement("SELECT * FROM tags WHERE id = ? AND contentId = ?");
+ statement.setString(1, id);
+ statement.setString(2, contentId);
+ ResultSet resultSet = statement.executeQuery();
+ return resultSet.next();
+ }
+}
diff --git a/src/main/java/com/adnan/server/handlers/HashtagHandler.java b/src/main/java/com/adnan/server/handlers/HashtagHandler.java
new file mode 100644
index 0000000..a4ea907
--- /dev/null
+++ b/src/main/java/com/adnan/server/handlers/HashtagHandler.java
@@ -0,0 +1,61 @@
+package com.adnan.server.handlers;
+
+import com.adnan.server.controllers.HashtagController;
+import com.adnan.server.controllers.MessageController;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.sql.SQLException;
+
+public class HashtagHandler implements HttpHandler {
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ HashtagController hashtagController;
+ try {
+ hashtagController = new HashtagController();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ String method = exchange.getRequestMethod();
+ String path = exchange.getRequestURI().getPath();
+ String response = "";
+ String[] splittedPath = path.split("/");
+ switch (method) {
+ case "GET":
+ if (splittedPath.length == 3) {
+ try {
+ response = hashtagController.getContents(splittedPath[2]);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ else response = "NOT A VALID REQUEST!!!";
+ break;
+ case "POST":
+ if (splittedPath.length == 4) {
+ try {
+ response = hashtagController.addHashtag(splittedPath[2], splittedPath[3]);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ else response = "NOT A VALID REQUEST!!!";
+ break;
+ case "DELETE":
+ if (splittedPath.length == 4) {
+ try {
+ response = hashtagController.deleteHashtag(splittedPath[2], splittedPath[3]);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ else response = "NOT A VALID REQUEST!!!";
+ }
+ exchange.sendResponseHeaders(200, response.getBytes().length);
+ OutputStream os = exchange.getResponseBody();
+ os.write(response.getBytes());
+ os.close();
+ }
+}
diff --git a/src/main/java/com/adnan/server/handlers/LikeHandler.java b/src/main/java/com/adnan/server/handlers/LikeHandler.java
index fc4584d..2d28011 100644
--- a/src/main/java/com/adnan/server/handlers/LikeHandler.java
+++ b/src/main/java/com/adnan/server/handlers/LikeHandler.java
@@ -49,6 +49,7 @@ else if (splittedPath.length == 4 && splittedPath[2].equals("liked")) {
case "POST":
if (splittedPath.length == 4) {
try {
+ System.out.println(splittedPath[2] + " " + splittedPath[3]);
response = likeController.addLike(splittedPath[2], splittedPath[3]);
} catch (SQLException e) {
throw new RuntimeException(e);
diff --git a/src/main/java/com/adnan/server/handlers/MediaHandler.java b/src/main/java/com/adnan/server/handlers/MediaHandler.java
new file mode 100644
index 0000000..984395e
--- /dev/null
+++ b/src/main/java/com/adnan/server/handlers/MediaHandler.java
@@ -0,0 +1,74 @@
+package com.adnan.server.handlers;
+
+import com.adnan.server.controllers.UserController;
+import com.adnan.server.utils.ExtractUserAuth;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.sql.SQLException;
+import java.util.Collections;
+
+public class MediaHandler implements HttpHandler {
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ UserController userController = null;
+ try {
+ userController = new UserController();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ String response = "";
+ String method = exchange.getRequestMethod();
+ String path = exchange.getRequestURI().getPath();
+ String[] splittedPath = path.split("/");
+ // ip:port/media/userID/mediaName/mediaType
+ if (splittedPath.length != 5) {
+ response = "NOT A VALID REQUEST";
+ } else switch (method) {
+ case "GET":
+ File file;
+ file = new File("C:\\Users\\3500-\\Desktop\\LinkedIn Project\\LinkedInClient\\src\\main\\resources\\org\\example\\linkedinclient\\assets" + "\\" + splittedPath[3] + "." + splittedPath[4]);
+ if (!file.exists()) {
+ response = "no file";
+ break;
+ }
+ exchange.getResponseHeaders().put("Content-Type", Collections.singletonList(splittedPath[4]));
+ exchange.sendResponseHeaders(200, file.length());
+ OutputStream outputStream = exchange.getResponseBody();
+ Files.copy(file.toPath(), outputStream);
+ outputStream.close();
+ return;
+ case "POST":
+ try {
+ if (!userController.userExists(splittedPath[2])) {
+ response = "USER NOT FOUND!";
+ break;
+ }
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ if (!splittedPath[2].equals(ExtractUserAuth.extract(exchange))) {
+ response = "NOT ALLOWED!";
+ break;
+ }
+ System.out.println("kkkkkkk");
+// Files.copy(exchange.getRequestBody(), Path("C:\\Users\\3500-\\Desktop\\LinkedIn Project\\src\\main\\java\\com\\adnan\\server\\" , splittedPath[2], splittedPath[3] + "." + splittedPath[4]), StandardCopyOption.REPLACE_EXISTING);
+ System.out.println("llllll");
+ response = "successful!";
+ break;
+ default:
+ response = "NOT A VALID REQUEST";
+ break;
+ }
+ System.out.println(response);
+
+ exchange.sendResponseHeaders(200, response.getBytes().length);
+ OutputStream os = exchange.getResponseBody();
+ os.write(response.getBytes());
+ os.close();
+ }
+}
diff --git a/src/main/java/com/adnan/server/logo.png b/src/main/java/com/adnan/server/logo.png
new file mode 100644
index 0000000..08aabe0
Binary files /dev/null and b/src/main/java/com/adnan/server/logo.png differ
diff --git a/src/main/java/com/adnan/server/models/Bio.java b/src/main/java/com/adnan/server/models/Bio.java
index cf732bc..bc6bc89 100644
--- a/src/main/java/com/adnan/server/models/Bio.java
+++ b/src/main/java/com/adnan/server/models/Bio.java
@@ -5,7 +5,7 @@
public class Bio {
@JsonProperty("userId")
private String userId;
- @JsonProperty("biography")
+ @JsonProperty("bioText")
private String bioText;
@JsonProperty("location")
diff --git a/src/main/java/com/adnan/server/models/Content.java b/src/main/java/com/adnan/server/models/Content.java
index edfb9e4..26a307e 100644
--- a/src/main/java/com/adnan/server/models/Content.java
+++ b/src/main/java/com/adnan/server/models/Content.java
@@ -2,6 +2,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
import java.util.Date;
public class Content {
@@ -17,6 +18,8 @@ public class Content {
private Date timeStamp;
@JsonProperty("commentsNumber")
private int commentsNumber;
+ @JsonProperty("mediaPaths")
+ private ArrayList mediaPaths;
public Content(String posterId, String content) {
this.postId = posterId + System.currentTimeMillis();
@@ -25,11 +28,13 @@ public Content(String posterId, String content) {
this.timeStamp = new Date(System.currentTimeMillis());
this.likesNumber = 0;
this.commentsNumber = 0;
+ mediaPaths = new ArrayList<>();
}
public Content() {
this.likesNumber = 0;
this.commentsNumber = 0;
this.timeStamp = new Date(System.currentTimeMillis());
+ mediaPaths = new ArrayList<>();
}
public String getPostId() {
@@ -90,4 +95,12 @@ public void decreaseComment() {
public void setLikesNumber(int likesNumber) {
this.likesNumber = likesNumber;
}
+
+ public ArrayList getMediaPaths() {
+ return mediaPaths;
+ }
+
+ public void setMediaPaths(ArrayList mediaPaths) {
+ this.mediaPaths = mediaPaths;
+ }
}
diff --git a/src/main/java/com/adnan/server/models/Hashtag.java b/src/main/java/com/adnan/server/models/Hashtag.java
new file mode 100644
index 0000000..86f73f6
--- /dev/null
+++ b/src/main/java/com/adnan/server/models/Hashtag.java
@@ -0,0 +1,32 @@
+package com.adnan.server.models;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Hashtag {
+ @JsonProperty("id")
+ private String id;
+ @JsonProperty("contentId")
+ private String contentId;
+
+ public Hashtag(String id, String contentId) {
+ this.id = id;
+ this.contentId = contentId;
+ }
+ public Hashtag() {}
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getContentId() {
+ return contentId;
+ }
+
+ public void setContentId(String contentId) {
+ this.contentId = contentId;
+ }
+}
diff --git a/src/main/java/com/adnan/server/models/Post.java b/src/main/java/com/adnan/server/models/Post.java
index 4129ef0..44b9e77 100644
--- a/src/main/java/com/adnan/server/models/Post.java
+++ b/src/main/java/com/adnan/server/models/Post.java
@@ -6,10 +6,22 @@
public class Post extends Content {
+ @JsonProperty
+ private boolean hasMedia;
public Post(String posterId, String content) {
super(posterId, content);
+ hasMedia = false;
}
public Post() {
super();
+ hasMedia = false;
+ }
+
+ public void setHasMedia(boolean hasMedia) {
+ this.hasMedia = hasMedia;
+ }
+
+ public boolean HasMedia() {
+ return hasMedia;
}
}
diff --git a/src/main/java/org/example/Main.java b/src/main/java/org/example/Main.java
index fef853b..8cefd7d 100644
--- a/src/main/java/org/example/Main.java
+++ b/src/main/java/org/example/Main.java
@@ -6,6 +6,7 @@
import java.net.InetSocketAddress;
public class Main {
+
public static void main(String[] args) throws IOException, InterruptedException {
HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
server.createContext("/users", new UserHandler());
@@ -20,6 +21,8 @@ public static void main(String[] args) throws IOException, InterruptedException
server.createContext("/likes", new LikeHandler());
server.createContext("/comments", new CommentHandler());
server.createContext("/messages", new MessageHandler());
+ server.createContext("/tags", new HashtagHandler());
+ server.createContext("/media", new MediaHandler());
server.start();
}
diff --git a/untitled/.idea/compiler.xml b/untitled/.idea/compiler.xml
new file mode 100644
index 0000000..d9e3477
--- /dev/null
+++ b/untitled/.idea/compiler.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/untitled/.idea/jarRepositories.xml b/untitled/.idea/jarRepositories.xml
new file mode 100644
index 0000000..712ab9d
--- /dev/null
+++ b/untitled/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/untitled/.idea/workspace.xml b/untitled/.idea/workspace.xml
new file mode 100644
index 0000000..36838b1
--- /dev/null
+++ b/untitled/.idea/workspace.xml
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1719992605317
+
+
+ 1719992605317
+
+
+
+
\ No newline at end of file