Files
org_roam/output/20241210232054-uml_fyp.html

1261 lines
32 KiB
HTML
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2025-12-28 Sun 20:49 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>uml_fyp</title>
<meta name="generator" content="Org Mode" />
<style type="text/css">
#content { max-width: 60em; margin: auto; }
.title { text-align: center;
margin-bottom: .2em; }
.subtitle { text-align: center;
font-size: medium;
font-weight: bold;
margin-top:0; }
.todo { font-family: monospace; color: red; }
.done { font-family: monospace; color: green; }
.priority { font-family: monospace; color: orange; }
.tag { background-color: #eee; font-family: monospace;
padding: 2px; font-size: 80%; font-weight: normal; }
.timestamp { color: #bebebe; }
.timestamp-kwd { color: #5f9ea0; }
.org-right { margin-left: auto; margin-right: 0px; text-align: right; }
.org-left { margin-left: 0px; margin-right: auto; text-align: left; }
.org-center { margin-left: auto; margin-right: auto; text-align: center; }
.underline { text-decoration: underline; }
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
p.verse { margin-left: 3%; }
pre {
border: 1px solid #e6e6e6;
border-radius: 3px;
background-color: #f2f2f2;
padding: 8pt;
font-family: monospace;
overflow: auto;
margin: 1.2em;
}
pre.src {
position: relative;
overflow: auto;
}
pre.src:before {
display: none;
position: absolute;
top: -8px;
right: 12px;
padding: 3px;
color: #555;
background-color: #f2f2f299;
}
pre.src:hover:before { display: inline; margin-top: 14px;}
/* Languages per Org manual */
pre.src-asymptote:before { content: 'Asymptote'; }
pre.src-awk:before { content: 'Awk'; }
pre.src-authinfo::before { content: 'Authinfo'; }
pre.src-C:before { content: 'C'; }
/* pre.src-C++ doesn't work in CSS */
pre.src-clojure:before { content: 'Clojure'; }
pre.src-css:before { content: 'CSS'; }
pre.src-D:before { content: 'D'; }
pre.src-ditaa:before { content: 'ditaa'; }
pre.src-dot:before { content: 'Graphviz'; }
pre.src-calc:before { content: 'Emacs Calc'; }
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
pre.src-fortran:before { content: 'Fortran'; }
pre.src-gnuplot:before { content: 'gnuplot'; }
pre.src-haskell:before { content: 'Haskell'; }
pre.src-hledger:before { content: 'hledger'; }
pre.src-java:before { content: 'Java'; }
pre.src-js:before { content: 'Javascript'; }
pre.src-latex:before { content: 'LaTeX'; }
pre.src-ledger:before { content: 'Ledger'; }
pre.src-lisp:before { content: 'Lisp'; }
pre.src-lilypond:before { content: 'Lilypond'; }
pre.src-lua:before { content: 'Lua'; }
pre.src-matlab:before { content: 'MATLAB'; }
pre.src-mscgen:before { content: 'Mscgen'; }
pre.src-ocaml:before { content: 'Objective Caml'; }
pre.src-octave:before { content: 'Octave'; }
pre.src-org:before { content: 'Org mode'; }
pre.src-oz:before { content: 'OZ'; }
pre.src-plantuml:before { content: 'Plantuml'; }
pre.src-processing:before { content: 'Processing.js'; }
pre.src-python:before { content: 'Python'; }
pre.src-R:before { content: 'R'; }
pre.src-ruby:before { content: 'Ruby'; }
pre.src-sass:before { content: 'Sass'; }
pre.src-scheme:before { content: 'Scheme'; }
pre.src-screen:before { content: 'Gnu Screen'; }
pre.src-sed:before { content: 'Sed'; }
pre.src-sh:before { content: 'shell'; }
pre.src-sql:before { content: 'SQL'; }
pre.src-sqlite:before { content: 'SQLite'; }
/* additional languages in org.el's org-babel-load-languages alist */
pre.src-forth:before { content: 'Forth'; }
pre.src-io:before { content: 'IO'; }
pre.src-J:before { content: 'J'; }
pre.src-makefile:before { content: 'Makefile'; }
pre.src-maxima:before { content: 'Maxima'; }
pre.src-perl:before { content: 'Perl'; }
pre.src-picolisp:before { content: 'Pico Lisp'; }
pre.src-scala:before { content: 'Scala'; }
pre.src-shell:before { content: 'Shell Script'; }
pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
/* additional language identifiers per "defun org-babel-execute"
in ob-*.el */
pre.src-cpp:before { content: 'C++'; }
pre.src-abc:before { content: 'ABC'; }
pre.src-coq:before { content: 'Coq'; }
pre.src-groovy:before { content: 'Groovy'; }
/* additional language identifiers from org-babel-shell-names in
ob-shell.el: ob-shell is the only babel language using a lambda to put
the execution function name together. */
pre.src-bash:before { content: 'bash'; }
pre.src-csh:before { content: 'csh'; }
pre.src-ash:before { content: 'ash'; }
pre.src-dash:before { content: 'dash'; }
pre.src-ksh:before { content: 'ksh'; }
pre.src-mksh:before { content: 'mksh'; }
pre.src-posh:before { content: 'posh'; }
/* Additional Emacs modes also supported by the LaTeX listings package */
pre.src-ada:before { content: 'Ada'; }
pre.src-asm:before { content: 'Assembler'; }
pre.src-caml:before { content: 'Caml'; }
pre.src-delphi:before { content: 'Delphi'; }
pre.src-html:before { content: 'HTML'; }
pre.src-idl:before { content: 'IDL'; }
pre.src-mercury:before { content: 'Mercury'; }
pre.src-metapost:before { content: 'MetaPost'; }
pre.src-modula-2:before { content: 'Modula-2'; }
pre.src-pascal:before { content: 'Pascal'; }
pre.src-ps:before { content: 'PostScript'; }
pre.src-prolog:before { content: 'Prolog'; }
pre.src-simula:before { content: 'Simula'; }
pre.src-tcl:before { content: 'tcl'; }
pre.src-tex:before { content: 'TeX'; }
pre.src-plain-tex:before { content: 'Plain TeX'; }
pre.src-verilog:before { content: 'Verilog'; }
pre.src-vhdl:before { content: 'VHDL'; }
pre.src-xml:before { content: 'XML'; }
pre.src-nxml:before { content: 'XML'; }
/* add a generic configuration mode; LaTeX export needs an additional
(add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
pre.src-conf:before { content: 'Configuration File'; }
table { border-collapse:collapse; }
caption.t-above { caption-side: top; }
caption.t-bottom { caption-side: bottom; }
td, th { vertical-align:top; }
th.org-right { text-align: center; }
th.org-left { text-align: center; }
th.org-center { text-align: center; }
td.org-right { text-align: right; }
td.org-left { text-align: left; }
td.org-center { text-align: center; }
dt { font-weight: bold; }
.footpara { display: inline; }
.footdef { margin-bottom: 1em; }
.figure { padding: 1em; }
.figure p { text-align: center; }
.equation-container {
display: table;
text-align: center;
width: 100%;
}
.equation {
vertical-align: middle;
}
.equation-label {
display: table-cell;
text-align: right;
vertical-align: middle;
}
.inlinetask {
padding: 10px;
border: 2px solid gray;
margin: 10px;
background: #ffffcc;
}
#org-div-home-and-up
{ text-align: right; font-size: 70%; white-space: nowrap; }
textarea { overflow-x: auto; }
.linenr { font-size: smaller }
.code-highlighted { background-color: #ffff00; }
.org-info-js_info-navigation { border-style: none; }
#org-info-js_console-label
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
.org-info-js_search-highlight
{ background-color: #ffff00; color: #000000; font-weight: bold; }
.org-svg { }
</style>
<link rel="stylesheet" href="/assets/styles/style.css" />
<link rel="stylesheet" href="/assets/styles/bigger-picture.min.css" />
<link rel="stylesheet" href="/assets/styles/media.css" />
<script src="/assets/scripts/script.js" defer></script>
<script src="/assets/scripts/search.js" defer></script>
<script src="/assets/scripts/bigger-picture.min.js" defer></script>
<script src="/assets/scripts/svg-pan-zoom.min.js" defer></script>
<script src="/assets/scripts/gallery-init.js" defer></script>
<script>
window.MathJax = {
tex: {
ams: {
multlineWidth: '85%'
},
tags: 'ams',
tagSide: 'right',
tagIndent: '.8em'
},
chtml: {
scale: 1.0,
displayAlign: 'center',
displayIndent: '0em'
},
svg: {
scale: 1.0,
displayAlign: 'center',
displayIndent: '0em'
},
output: {
font: 'mathjax-modern',
displayOverflow: 'overflow'
}
};
</script>
<script
id="MathJax-script"
async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js">
</script>
</head>
<body>
<div id="preamble" class="status">
<div class="banner-header">
<div class="banner-left">
<a href="/20241210233721-brain_moc.html"> <img src="/assets/gr.png" alt="Site Logo" class="banner-logo" /> </a>
<div id="updated">Updated: 2025-12-28 Sun 19:48</div>
</div>
<div class="banner-search">
<input id="search-box"
type="search"
placeholder="Search notes…"
aria-label="Search notes"
autocomplete="off" />
<div id="search-results"></div>
</div>
<button id="close-all">Close All</button>
</div>
</div>
<div id="stack-root">
<div class="stack-track">
<article class="stack-pane pane-root" data-url="/20241210232054-uml_fyp.html">
<div id="content" class="content">
<div class="title-section">
<div class="title-controls">
<button class="pane-fullscreen" aria-label="Fullscreen">F</button>
<button class="pane-edit" aria-label="Edit pane">E</button>
<button class="pane-close" aria-label="Close pane">×</button>
</div>
<h1 class="title">uml<sub>fyp</sub></h1>
<div class="title-metadata">
<span class="metadata-item">
<span class="metadata-label">planted:</span>
<span class="metadata-value">2024-12-10</span>
</span>
<span class="metadata-item">
<span class="metadata-label">last tended to:</span>
<span class="metadata-value">2025-12-28</span>
</span>
</div>
</div>
<div id="outline-container-orgc3688e1" class="outline-2">
<h2 id="orgc3688e1"><a href="#orgc3688e1">Class diagram</a></h2>
<div class="outline-text-2" id="text-orgc3688e1">
</div>
<div id="outline-container-org2d9f8e0" class="outline-3">
<h3 id="org2d9f8e0"><a href="#org2d9f8e0">class 2:</a></h3>
<div class="outline-text-3" id="text-org2d9f8e0">
<p>
@startuml
skinparam classAttributeIconSize 0
skinparam packageStyle rectangle
skinparam linetype ortho
left to right direction
</p>
<p>
&rsquo; Entity Layer
rectangle &ldquo;Entity Layer&rdquo; as EntityLayer #E3F2FD {
class User {
+id: Long
+roles: Set&lt;String&gt;
+firstName: String
+lastName: String
+username: String
+password: String
+confirmPassword: String
+email: String
+phoneNumber: String
+picture: byte[]
}
</p>
<p>
class Workspace {
+id: Long
+name: String
+description: String
+fileCount: int
+noteCount: int
+lastAccessed: LocalDateTime
+dateCreated: LocalDateTime
}
</p>
<p>
class Library {
+id: Long
+name: String
+description: String
+dateCreated: LocalDateTime
+lastAccessed: LocalDateTime
}
</p>
<p>
class Page {
+id: Long
+name: String
+workspaceId: Long
+content: Text
+height: int
+width: int
}
</p>
<p>
class FileMetadata {
+id: Long
+fileUrl: String
+userId: String
+description: String
+fileData: byte[]
+fileName: String
+fileType: String
}
</p>
<p>
class AiChat {
+id: Long
+name: String
+workspaceId: Long
+createdAt: LocalDateTime
+messages: List&lt;AIChatMessage&gt;
}
}
</p>
<p>
&rsquo; Repository Layer
rectangle &ldquo;Repository Layer&rdquo; as RepositoryLayer #E8F5E9 {
class AiChatRepository
class FileMetadataRepository
class LibraryRepository
class PageRepository
class UserRepository
class WorkspaceRepository
class RegisterRepository
class AuthRepository
}
</p>
<p>
&rsquo; Service Layer
rectangle &ldquo;Service Layer&rdquo; as ServiceLayer #FFF3E0 {
class AiChatService
class AuthService
class FileMetadataService
class LibraryService
class PageService
class RegisterService
class UserService
class WorkspaceService
}
</p>
<p>
&rsquo; Controller Layer
rectangle &ldquo;Controller Layer&rdquo; as ControllerLayer #F3E5F5 {
class AiChatController
class AiChatWebSocketController
class AuthController
class FileMetadataController
class LibraryController
class PageController
class RegisterController
class UserController
class WorkspaceController
}
</p>
<p>
&rsquo; External Python Microservice
rectangle &ldquo;External NLP Module (Python FastAPI)&rdquo; as ExternalNLP #FCE4EC {
class FastAPINLPServer {
+/extract<sub>text</sub>
+/keywords
+/tfidf<sub>keywords</sub>
+/summarize
+/ner
}
}
</p>
<p>
rectangle &ldquo;Frontend Core&rdquo; as FrontendCore {
class AboutComponent
class AccessibilityComponent
class ContactComponent
class ForgotPasswordComponent
class LoginComponent
class LoginService
class PrivacyComponent
class RegisterComponent
class RegisterService
class SecurityComponent
class TermsComponent
</p>
<p>
LoginComponent &#x2013;&gt; LoginService
RegisterComponent &#x2013;&gt; RegisterService
</p>
<p>
LoginService ..&gt; AuthController : REST
RegisterService ..&gt; RegisterController : REST
}
</p>
<p>
rectangle &ldquo;Frontend Entities&rdquo; as FrontendEntities {
class AiChatComponent
class DashboardComponent
class DefaultLayoutComponent
class HomeComponent
class LibraryComponent
class ProfileComponent
class WorkspacePageComponent
class WorkspacesComponent
</p>
<p>
class AiChatServiceFE
class DashboardServiceFE
class LayoutServiceFE
class HomeServiceFE
class LibraryServiceFE
class ProfileServiceFE
class WorkspacePageServiceFE
class WorkspacesServiceFE
</p>
<p>
AiChatComponent &#x2013;&gt; AiChatServiceFE
DashboardComponent &#x2013;&gt; DashboardServiceFE
DefaultLayoutComponent &#x2013;&gt; LayoutServiceFE
DefaultLayoutComponent &#x2013;&gt; LoginComponent
DefaultLayoutComponent &#x2013;&gt; RegisterComponent
HomeComponent &#x2013;&gt; HomeServiceFE
LibraryComponent &#x2013;&gt; LibraryServiceFE
ProfileComponent &#x2013;&gt; ProfileServiceFE
WorkspacePageComponent &#x2013;&gt; WorkspacePageServiceFE
WorkspacesComponent &#x2013;&gt; WorkspacesServiceFE
</p>
<p>
ForgotPasswordComponent ..&gt; UserController : REST
AiChatServiceFE ..&gt; AiChatController : REST
AiChatServiceFE ..&gt; AiChatWebSocketController : WebSocket
</p>
<p>
DashboardServiceFE ..&gt; WorkspaceController : REST
DashboardServiceFE ..&gt; PageController : REST
DashboardServiceFE ..&gt; AiChatController : REST
</p>
<p>
LayoutServiceFE ..&gt; UserController : REST
</p>
<p>
HomeServiceFE ..&gt; AuthController : REST
</p>
<p>
LibraryServiceFE ..&gt; LibraryController : REST
LibraryServiceFE ..&gt; FileMetadataController : REST
</p>
<p>
ProfileServiceFE ..&gt; UserController : REST
</p>
<p>
WorkspacePageServiceFE ..&gt; PageController : REST
WorkspacePageServiceFE ..&gt; FileMetadataController : REST
WorkspacePageServiceFE ..&gt; AiChatController : REST
</p>
<p>
WorkspacesServiceFE ..&gt; WorkspaceController : REST
AboutComponent &#x2013;&gt; ContactComponent
AboutComponent &#x2013;&gt; TermsComponent
AboutComponent &#x2013;&gt; PrivacyComponent
}
</p>
<p>
class AngularClient
AngularClient &#x2013;&gt; FrontendCore
AngularClient &#x2013;&gt; FrontendEntities
AngularClient ..&gt; FastAPINLPServer : REST
</p>
<p>
&rsquo; Entity Relationships
User &ldquo;1&rdquo; &#x2013;&gt; &ldquo;many&rdquo; Library
User &ldquo;1&rdquo; &#x2013;&gt; &ldquo;many&rdquo; Workspace
Library &ldquo;1&rdquo; &#x2013;&gt; &ldquo;many&rdquo; Workspace
Library &ldquo;1&rdquo; &#x2013;&gt; &ldquo;many&rdquo; FileMetadata
Workspace &ldquo;1&rdquo; &#x2013;&gt; &ldquo;many&rdquo; Page
Workspace &ldquo;1&rdquo; &#x2013;&gt; &ldquo;many&rdquo; FileMetadata
Workspace &ldquo;1&rdquo; &#x2013;&gt; &ldquo;many&rdquo; AiChat
</p>
<p>
&rsquo; Controller → Service
AiChatController &#x2013;&gt; AiChatService
AiChatWebSocketController &#x2013;&gt; AiChatService
AuthController &#x2013;&gt; AuthService
FileMetadataController &#x2013;&gt; FileMetadataService
LibraryController &#x2013;&gt; LibraryService
PageController &#x2013;&gt; PageService
RegisterController &#x2013;&gt; RegisterService
UserController &#x2013;&gt; UserService
WorkspaceController &#x2013;&gt; WorkspaceService
</p>
<p>
&rsquo; Service → Repository
AiChatService &#x2013;&gt; AiChatRepository
AuthService &#x2013;&gt; AuthRepository
FileMetadataService &#x2013;&gt; FileMetadataRepository
LibraryService &#x2013;&gt; LibraryRepository
PageService &#x2013;&gt; PageRepository
RegisterService &#x2013;&gt; RegisterRepository
UserService &#x2013;&gt; UserRepository
WorkspaceService &#x2013;&gt; WorkspaceRepository
</p>
<p>
&rsquo; Repository → Entity
AiChatRepository &#x2013;&gt; AiChat
FileMetadataRepository &#x2013;&gt; FileMetadata
LibraryRepository &#x2013;&gt; Library
PageRepository &#x2013;&gt; Page
UserRepository &#x2013;&gt; User
WorkspaceRepository &#x2013;&gt; Workspace
RegisterRepository &#x2013;&gt; User
AuthRepository &#x2013;&gt; User
</p>
<p>
@enduml
</p>
</div>
</div>
<div id="outline-container-orgc653b2b" class="outline-3">
<h3 id="orgc653b2b"><a href="#orgc653b2b">authentication sequence diagram:</a></h3>
<div class="outline-text-3" id="text-orgc653b2b">
<p>
@startuml
title Full Authentication Flow - Registration to Secured Access
</p>
<p>
skinparam shadowing true
skinparam packageStyle rectangle
skinparam handwritten false
skinparam linetype polyline
skinparam ParticipantPadding 20
skinparam maxMessageSize 150
</p>
<p>
actor User
</p>
<p>
<code>= Registration Process =</code>
</p>
<p>
box &ldquo;Client&rdquo; #E3F2FD
participant UserClient as &ldquo;User&rdquo;
end box
</p>
<p>
box &ldquo;Backend - Registration&rdquo; #E8F5E9
participant RegisterController
participant UserService
end box
</p>
<p>
UserClient -&gt; RegisterController : POST /register\n(username, password, confirmPassword)
RegisterController -&gt; RegisterController : Check if passwords match
alt Passwords do not match
RegisterController &#x2013;&gt; UserClient : 400 Bad Request (Passwords mismatch)
return
end
RegisterController -&gt; RegisterController : Hash password (BCrypt)
RegisterController -&gt; RegisterController : Load default profile image
RegisterController -&gt; UserService : createUser(user)
RegisterController &#x2013;&gt; UserClient : 200 OK (User Created)
</p>
<p>
<code>= Authentication Process =</code>
</p>
<p>
box &ldquo;Backend - Authentication&rdquo; #FFF3E0
participant AuthController
participant AuthenticationManager
participant JwtUtil
end box
</p>
<p>
UserClient -&gt; AuthController : POST /auth/login\n(username, password)
AuthController -&gt; AuthenticationManager : Authenticate credentials
alt Valid credentials
AuthController -&gt; JwtUtil : generateToken(userDetails, userId)
AuthController &#x2013;&gt; UserClient : 200 OK + JWT
else Invalid credentials
AuthController &#x2013;&gt; UserClient : 401 Unauthorized
return
end
</p>
<p>
<code>= Accessing a Protected API =</code>
</p>
<p>
box &ldquo;Security Filter Chain&rdquo; #F3E5F5
participant JwtRequestFilter
participant UserDetailsService
participant JwtUtilFilter as &ldquo;JwtUtil&rdquo;
end box
</p>
<p>
UserClient -&gt; JwtRequestFilter : Request with Authorization header
JwtRequestFilter -&gt; JwtUtilFilter : extractUsername(jwt)
JwtRequestFilter -&gt; UserDetailsService : loadUserByUsername
JwtRequestFilter -&gt; JwtUtilFilter : validateToken(jwt, userDetails)
alt Valid token
JwtRequestFilter -&gt; SecurityContext : Set authentication
else Invalid token
JwtRequestFilter -&gt; JwtRequestFilter : Log and skip authentication
end
JwtRequestFilter &#x2013;&gt; UserClient : Continue filter chain
</p>
<p>
<code>= @JwtRequired Secured Method Access =</code>
</p>
<p>
box &ldquo;AOP - Method Security&rdquo; #E1F5FE
participant JwtAspect
participant JwtUtilAspect as &ldquo;JwtUtil&rdquo;
end box
</p>
<p>
UserClient -&gt; JwtAspect : Call method annotated with @JwtRequired
JwtAspect -&gt; JwtAspect : Extract JWT from header
JwtAspect -&gt; JwtUtilAspect : extractUsername(jwt)
JwtAspect -&gt; SecurityContext : Get UserDetails
JwtAspect -&gt; JwtUtilAspect : validateToken(jwt, userDetails)
alt Token valid and user matches
JwtAspect &#x2013;&gt; UserClient : Proceed to method execution
else Invalid/mismatched token
JwtAspect &#x2013;&gt; UserClient : Unauthorized exception
return
end
</p>
<p>
@enduml
</p>
</div>
</div>
<div id="outline-container-orgae45afc" class="outline-3">
<h3 id="orgae45afc"><a href="#orgae45afc">class</a></h3>
<div class="outline-text-3" id="text-orgae45afc">
<p>
@startuml
skinparam classAttributeIconSize 0
skinparam packageStyle rectangle
</p>
<p>
package &ldquo;High-Level Overview&rdquo; {
</p>
<p>
&rsquo; Controller Layer
package &ldquo;Controller Layer&rdquo; {
class AiChatController
class AiChatWebSocketController
class AuthController
class FileMetadataController
class LibraryController
class PageController
class RegisterController
class UserController
class WorkspaceController
}
</p>
<p>
&rsquo; Service Layer
package &ldquo;Service Layer&rdquo; {
class AiChatService
class AuthService
class FileMetadataService
class LibraryService
class PageService
class RegisterService
class UserService
class WorkspaceService
}
</p>
<p>
&rsquo; Repository Layer
package &ldquo;Repository Layer&rdquo; {
class AiChatRepository
class FileMetadataRepository
class LibraryRepository
class PageRepository
class UserRepository
class WorkspaceRepository
class RegisterRepository
class AuthRepository
}
</p>
<p>
&rsquo; Entity Layer
package &ldquo;Entity Layer&rdquo; {
</p>
<p>
class User {
+id: Long
+roles: Set&lt;String&gt;
+firstName: String
+lastName: String
+username: String
+password: String
+confirmPassword: String
+email: String
+phoneNumber: String
+picture: byte[]
}
</p>
<p>
class Workspace {
+id: Long
+name: String
+description: String
+fileCount: int
+noteCount: int
+lastAccessed: LocalDateTime
+dateCreated: LocalDateTime
}
</p>
<p>
class Library {
+id: Long
+name: String
+description: String
+dateCreated: LocalDateTime
+lastAccessed: LocalDateTime
}
</p>
<p>
class Page {
+id: Long
+name: String
+workspaceId: Long
+content: Text
+height: int
+width: int
}
</p>
<p>
class FileMetadata {
+id: Long
+fileUrl: String
+userId: String
+description: String
+fileData: byte[]
+fileName: String
+fileType: String
}
</p>
<p>
class AiChat {
+id: Long
+name: String
+workspaceId: Long
+createdAt: LocalDateTime
+messages: List&lt;AIChatMessage&gt;
}
}
</p>
<p>
&rsquo; Python NLP Microservice
package &ldquo;External NLP Module (Python FastAPI)&rdquo; {
class FastAPINLPServer {
+/extract<sub>text</sub>
+/keywords
+/tfidf<sub>keywords</sub>
+/summarize
+/ner
}
}
</p>
<p>
&rsquo; Entity Relationships
User &ldquo;1&rdquo; &#x2013;&gt; &ldquo;many&rdquo; Library
User &ldquo;1&rdquo; &#x2013;&gt; &ldquo;many&rdquo; Workspace
Library &ldquo;1&rdquo; &#x2013;&gt; &ldquo;many&rdquo; Workspace
Library &ldquo;1&rdquo; &#x2013;&gt; &ldquo;many&rdquo; FileMetadata
Workspace &ldquo;1&rdquo; &#x2013;&gt; &ldquo;many&rdquo; Page
Workspace &ldquo;1&rdquo; &#x2013;&gt; &ldquo;many&rdquo; FileMetadata
Workspace &ldquo;1&rdquo; &#x2013;&gt; &ldquo;many&rdquo; AiChat
</p>
<p>
&rsquo; Controller → Service
AiChatController &#x2013;&gt; AiChatService
AiChatWebSocketController &#x2013;&gt; AiChatService
AuthController &#x2013;&gt; AuthService
FileMetadataController &#x2013;&gt; FileMetadataService
LibraryController &#x2013;&gt; LibraryService
PageController &#x2013;&gt; PageService
RegisterController &#x2013;&gt; RegisterService
UserController &#x2013;&gt; UserService
WorkspaceController &#x2013;&gt; WorkspaceService
</p>
<p>
&rsquo; Service → Repository
AiChatService &#x2013;&gt; AiChatRepository
AuthService &#x2013;&gt; AuthRepository
FileMetadataService &#x2013;&gt; FileMetadataRepository
LibraryService &#x2013;&gt; LibraryRepository
PageService &#x2013;&gt; PageRepository
RegisterService &#x2013;&gt; RegisterRepository
UserService &#x2013;&gt; UserRepository
WorkspaceService &#x2013;&gt; WorkspaceRepository
</p>
<p>
&rsquo; Repository → Entity
AiChatRepository &#x2013;&gt; AiChat
FileMetadataRepository &#x2013;&gt; FileMetadata
LibraryRepository &#x2013;&gt; Library
PageRepository &#x2013;&gt; Page
UserRepository &#x2013;&gt; User
WorkspaceRepository &#x2013;&gt; Workspace
RegisterRepository &#x2013;&gt; User
AuthRepository &#x2013;&gt; User
</p>
<p>
&rsquo; Frontend → NLP Server
</p>
<p>
}
</p>
<p>
&rsquo; Frontend Component
package &ldquo;Frontend&rdquo; {
class AngularClient
}
</p>
<p>
&rsquo; Angular communicates with both backends
AngularClient ..&gt; AiChatController : REST
AngularClient ..&gt; AiChatWebSocketController : WebSocket
AngularClient ..&gt; AuthController : REST
AngularClient ..&gt; PageController : REST
AngularClient ..&gt; FileMetadataController : REST
AngularClient ..&gt; WorkspaceController : REST
AngularClient ..&gt; LibraryController : REST
AngularClient ..&gt; RegisterController : REST
AngularClient ..&gt; UserController : REST
AngularClient ..&gt; FastAPINLPServer : REST
</p>
<p>
@enduml
</p>
</div>
</div>
<div id="outline-container-org6fe7f5f" class="outline-3">
<h3 id="org6fe7f5f"><a href="#org6fe7f5f">client-server</a></h3>
<div class="outline-text-3" id="text-org6fe7f5f">
<p>
@startuml
!pragma layout smetana
</p>
<p>
actor User
</p>
<p>
package &ldquo;Client Side (Angular)&rdquo; {
[Angular App] as Frontend
}
</p>
<p>
package &ldquo;Spring Boot Backend&rdquo; {
[Auth Controller]
[Note Controller]
[NLP Proxy Service]
[Spring Boot App] as Backend
}
</p>
<p>
package &ldquo;Database Layer&rdquo; {
database &ldquo;PostgreSQL Database&rdquo; as DB
}
</p>
<p>
package &ldquo;FastAPI NLP Server (Port 9010)&rdquo; {
[FastAPI NLP Service] as NLP
[Summarisation Endpoint] as SumEndpoint
[Keyword Extraction] as KeywordEndpoint
[NER Endpoint] as NEREndpoint
}
</p>
<p>
package &ldquo;External API&rdquo; {
[OpenAI API]
}
</p>
<p>
&rsquo; Interactions
User &#x2013;&gt; Frontend : Uses Web Interface
Frontend &#x2013;&gt; Backend : REST API Calls
Backend &#x2013;&gt; [Auth Controller] : Handles Auth
Backend &#x2013;&gt; [Note Controller] : Handles Notes
Backend &#x2013;&gt; [NLP Proxy Service] : Handles NLP Requests
[Auth Controller] &#x2013;&gt; DB : Access users table
[Note Controller] &#x2013;&gt; DB : Access notes table
[NLP Proxy Service] &#x2013;&gt; NLP : HTTP (port 9010)
NLP &#x2013;&gt; SumEndpoint : /summarise
NLP &#x2013;&gt; KeywordEndpoint : /keywords
NLP &#x2013;&gt; NEREndpoint : /ner
SumEndpoint &#x2013;&gt; [OpenAI API] : API call for contextual help
</p>
<p>
note right of Frontend
Angular app includes:
</p>
<ul class="org-ul">
<li>Note Editor</li>
<li>Summary View</li>
<li>Keyword Panel</li>
</ul>
<p>
end note
</p>
<p>
note right of Backend
Spring Boot includes:
</p>
<ul class="org-ul">
<li>Auth Controller</li>
<li>Note Controller</li>
<li>NLP Proxy Service (calls FastAPI)</li>
</ul>
<p>
end note
</p>
<p>
note right of NLP
FastAPI exposes endpoints for:
</p>
<ul class="org-ul">
<li>Summarisation (Pegasus)</li>
<li>Keyword Extraction (TF-IDF, YAKE)</li>
<li>NER (spaCy)</li>
</ul>
<p>
end note
@enduml
</p>
</div>
</div>
<div id="outline-container-orgf2791a4" class="outline-3">
<h3 id="orgf2791a4"><a href="#orgf2791a4">high level:</a></h3>
<div class="outline-text-3" id="text-orgf2791a4">
<p>
@startuml
skinparam componentStyle uml2
skinparam packageStyle rectangle
</p>
<p>
package &ldquo;Client (Frontend)&rdquo; {
[Angular UI]
}
</p>
<p>
package &ldquo;Java Backend (Spring Boot)&rdquo; {
[REST API Controller Layer]
[WebSocket Controller]
[Service Layer]
[Repository Layer]
[JPA Entities]
}
</p>
<p>
package &ldquo;Python NLP Service&rdquo; {
[FastAPI Server]
[Summarizer (Pegasus)]
[Keyword Extractor (YAKE / TF-IDF)]
[NER (spaCy)]
[Extract Text (Canvas Object)]
}
</p>
<p>
package &ldquo;External Services&rdquo; {
[OpenAI API]
[PostgreSQL DB]
}
</p>
<p>
&rsquo; Communication Arrows
[Angular UI] &#x2013;&gt; [REST API Controller Layer] : REST API (JSON)
[Angular UI] &#x2013;&gt; [WebSocket Controller] : WebSocket
</p>
<p>
[REST API Controller Layer] &#x2013;&gt; [Service Layer]
[WebSocket Controller] &#x2013;&gt; [Service Layer]
[Service Layer] &#x2013;&gt; [Repository Layer]
[Repository Layer] ..&gt; [JPA Entities] : uses
[Service Layer] &#x2013;&gt; [OpenAI API] : API calls
</p>
<p>
[Service Layer] &#x2013;&gt; [FastAPI Server] : REST (NLP Requests)
[FastAPI Server] &#x2013;&gt; [Summarizer (Pegasus)]
[FastAPI Server] &#x2013;&gt; [Keyword Extractor (YAKE / TF-IDF)]
[FastAPI Server] &#x2013;&gt; [NER (spaCy)]
[FastAPI Server] &#x2013;&gt; [Extract Text (Canvas Object)]
</p>
<p>
[Repository Layer] &#x2013;&gt; [PostgreSQL DB] : Hibernate ORM
@enduml
</p>
</div>
</div>
<div id="outline-container-org3abacd3" class="outline-3">
<h3 id="org3abacd3"><a href="#org3abacd3">title AI Chat + Workspace Workflow</a></h3>
<div class="outline-text-3" id="text-org3abacd3">
<p>
@startuml
title AI Chat + Workspace Workflow
</p>
<p>
skinparam shadowing true
skinparam packageStyle rectangle
skinparam handwritten false
skinparam linetype polyline
skinparam ParticipantPadding 20
skinparam maxMessageSize 150
</p>
<p>
actor User
</p>
<p>
<code>= AI Chat Session Creation =</code>
</p>
<p>
box &ldquo;Client&rdquo; #E3F2FD
participant AngularClient as &ldquo;User&rdquo;
end box
</p>
<p>
box &ldquo;Backend - AI Chat&rdquo; #E8F5E9
participant AiChatController
participant AiChatService
participant AiChatRepository
end box
</p>
<p>
box &ldquo;External NLP Service&rdquo; #FCE4EC
participant FastAPINLPServer as &ldquo;FastAPI NLP&rdquo;
end box
</p>
<p>
User -&gt; AngularClient : Open AI Chat page
AngularClient -&gt; AiChatController : POST /ai-chat\n(chat metadata)
AiChatController -&gt; AiChatService : createChat(chatDto)
AiChatService -&gt; AiChatRepository : save(chat)
AiChatService &#x2013;&gt; AiChatController : chatId
AiChatController &#x2013;&gt; AngularClient : 200 OK + chatId
</p>
<p>
User -&gt; AngularClient : Send message via WebSocket
AngularClient -&gt; AiChatWebSocketController : message
AiChatWebSocketController -&gt; AiChatService : handleMessage()
</p>
<p>
alt Message requires NLP
AiChatService -&gt; FastAPINLPServer : POST /summarize or /ner
FastAPINLPServer &#x2013;&gt; AiChatService : NLP result
end
</p>
<p>
AiChatService -&gt; AiChatRepository : update(chat with message)
AiChatWebSocketController &#x2013;&gt; AngularClient : Message response
</p>
<p>
<code>= Workspace Creation =</code>
</p>
<p>
box &ldquo;Backend - Workspace&rdquo; #FFF3E0
participant WorkspaceController
participant WorkspaceService
participant WorkspaceRepository
end box
</p>
<p>
User -&gt; AngularClient : Create Workspace
AngularClient -&gt; WorkspaceController : POST /workspace\n(name, description)
WorkspaceController -&gt; WorkspaceService : createWorkspace(dto)
WorkspaceService -&gt; WorkspaceRepository : save(workspace)
WorkspaceService &#x2013;&gt; WorkspaceController : workspaceId
WorkspaceController &#x2013;&gt; AngularClient : 200 OK + workspaceId
</p>
<p>
@enduml
</p>
</div>
</div>
</div>
<div id="outline-container-orge25d17d" class="outline-2">
<h2 id="orge25d17d"><a href="#orge25d17d">Screenshots:</a></h2>
<div class="outline-text-2" id="text-orge25d17d">
</div>
<div id="outline-container-orgee85374" class="outline-3">
<h3 id="orgee85374"><a href="#orgee85374">Draft 1:</a></h3>
<div class="outline-text-3" id="text-orgee85374">
<div id="orgc29c9b6" class="figure">
<p><img src="file:///home/zaine/master-folder/FYP/uml/draft1.png" alt="draft1.png" />
</p>
</div>
<p class="backlinks-section" id="backlinks">
Backlinks
</p>
<ul class="org-ul backlinks-list">
<li><a href="20241210012703-fyp.html#ID-7d199fbe-b0e7-48fd-b8a1-793044dbea01">fyp</a></li>
</ul>
</div>
</div>
</div>
</div>
</div></article></div></div>
<div id="postamble" class="status">
<footer>
<div class="copyright-container">
<div class="copyright">
Copyright &copy; 2022-2025 Zaine Qayyum. All rights reserved unless otherwise noted.</div></div>
<div class="generated">
Created with <a href="https://www.gnu.org/software/emacs/">Emacs</a> 30.2 (<a href="https://orgmode.org">Org</a> mode 9.7.11) on <a href="https://www.archlinux.org/">Arch</a> <a href="https://www.gnu.org">GNU</a>/<a href="https://www.kernel.org/">Linux</a>
</div>
</footer>
</div>
</body>
</html>