diff --git a/.gitignore b/.gitignore
index 51ea38f..c3d9586 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@
*.zip
*.tar.gz
*.rar
+*.txt
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
diff --git a/AdvancedProjectClassDiagram.png b/AdvancedProjectClassDiagram.png
new file mode 100644
index 0000000..b361bac
Binary files /dev/null and b/AdvancedProjectClassDiagram.png differ
diff --git a/AdvancedProjectTeam15.iml b/AdvancedProjectTeam15.iml
index c90834f..69cf51f 100644
--- a/AdvancedProjectTeam15.iml
+++ b/AdvancedProjectTeam15.iml
@@ -7,5 +7,6 @@
+
\ No newline at end of file
diff --git a/README.md b/README.md
index f2f791d..8e2bdad 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,72 @@
-# AdvancedProjectTeam15
\ No newline at end of file
+# AdvancedProjectTeam15
+
+This project represents a component of a larger application.
+This component has 2 main functionalities:
+1. Export user data from data services
+2. Delete user data from data services
+
+## Export
+So we made adding exporting methods easy, but at start we have only two methods, 1 implemented and 1 waiting to be implemented.
+The implemented method is the one that downloads the data to the user's device.
+Firstly, the function calls the export method for each service, each service stores the data as a text file then calls the PDFConvertor to convert the text files into PDF files.
+After that, the function calls the zip method to zip all the PDF files into one zip file.
+
+This method takes 2 parameters:
+1. The username of the user that wants to export his data, of course it considers the user's powers.
+2. The path of the folder that the user wants to download his data to.
+
+So we made adding exporting methods easy by implementing the factory design pattern, that also applies for the export methods for each service, which makes adding a new services to the system requires the minimum amount of changes ,also we considered that there are more than one type of compression, so we made the compression method as a factory design pattern, so we can add more compression methods easily.
+
+You can find the result in the directory called "output" in the src directory.
+## Delete
+We have two types of delete methods.
+1. Hard delete: which deletes all the user's data including the user's account, it also prevents creating a new account using the deleted account's username, this was implemented by adding the deletedUserArchive class.
+2. Soft delete: which deletes all the user's data except the user's account.
+
+We also made adding deleting methods easy by implementing the factory design pattern.
+We used the iterator design pattern to iterate over some services' data to preform clean delete to avoid any errors.
+
+## Using Services
+So we noticed that every service has its own interface, this gave us a sign that the system expects adding more services for the service family in the future.
+This is why we added a factory for each service and used it in our system without touching the services themselves.
+We also noticed that the user profile service didn't consider two important thins:
+1. Adding or updating a user with a blank username.
+2. Adding or updating a user with a username that has been hard deleted.
+3. Adding or updating a user with a username that already exists, since it stores in a hash map, so it will overwrite the old user without even notifying.
+
+And since we don't want to modify the user profile service, we used the proxy design pattern to create proxy user profile service that handles the previous cases as follows:
+1. Overriding the add and update methods to throw BlankUsernameException if the username is blank.
+2. Overriding the add and update methods to throw UserDeletedException if the username is in the deleted users archive.
+3. Overriding the add method to throw UserAlreadyExistsException if the username already exists.
+
+## Exceptions
+We tried our best to handle any expected exceptions and avoid any unexpected behavior.
+
+* Built-in Exceptions: we handled each as it should be handled.
+
+* Services exceptions: we handled the exceptions that may occur in the services, mainly:
+ * UserNotFoundException, BadRequestException: we handled them by keep throwing them until they reach the application function, since the application function is the one responsible for the wrong input.
+ * SystemBusyException: We handled it by retrying the request until it succeeds.
+
+* Custom Exceptions: we found that in some scenarios build in exceptions where not suitable, so we created our own:
+ * BlankUsernameException: we throw it when the user tries to add or update a user with a blank username.
+ * FileDeleteException: we throw it when the system fails to delete a file during the export operation.
+ * UnqualifiedUserException: we throw it when the user tries to export data that he is not qualified to export.
+ * UserAlreadyExistsException: we throw it when the user tries to add a user with a username that already exists.
+ * UserDeletedException: we throw it when the user tries to add or update a user with a username that has been hard deleted.
+
+## Logging
+Logging makes everything easier, so adding logging to our system was a must.
+To make it easier, we created our own logger class that handles all the logging operations and stores the logs in a text file in the "out/production/AdvancedProjectTeam15/edu/najah/cap/logs" directory.
+This way, we can easily change the logging options in one place.
+Other methods can use the logger by calling the static method "log" in the logger class.
+
+## Conclusion
+We mainly used the following design patterns:
+* Factory design pattern: to make the system more flexible and easier to add new services, export methods, delete methods, and compression methods.
+* Proxy design pattern: to enhance the user profile service by handling some cases that the user profile service didn't handle without modifying the user profile service itself.
+* Iterator design pattern: to iterate over some services' data to preform clean delete to avoid any errors.
+* Singleton design pattern: we combine the singleton design pattern with the proxy design pattern to enhance the performance of the system by creating only one instance of the user profile service in the proxy user profile service.
+
+## Class Diagram
+
\ No newline at end of file
diff --git a/src/edu/najah/cap/activity/IUserActivityService.java b/src/edu/najah/cap/activity/IUserActivityService.java
index c3cf33d..6825c37 100644
--- a/src/edu/najah/cap/activity/IUserActivityService.java
+++ b/src/edu/najah/cap/activity/IUserActivityService.java
@@ -1,12 +1,16 @@
package edu.najah.cap.activity;
+import edu.najah.cap.exceptions.BadRequestException;
+import edu.najah.cap.exceptions.NotFoundException;
+import edu.najah.cap.exceptions.SystemBusyException;
+
import java.util.List;
public interface IUserActivityService {
void addUserActivity(UserActivity userActivity);
- List getUserActivity(String userId);
+ List getUserActivity(String userId) throws SystemBusyException, BadRequestException, NotFoundException;
- void removeUserActivity(String userId, String id);
+ void removeUserActivity(String userId, String id) throws SystemBusyException, BadRequestException, NotFoundException;
}
diff --git a/src/edu/najah/cap/activity/UserActivityService.java b/src/edu/najah/cap/activity/UserActivityService.java
index 37d2e48..388bf5c 100644
--- a/src/edu/najah/cap/activity/UserActivityService.java
+++ b/src/edu/najah/cap/activity/UserActivityService.java
@@ -1,5 +1,12 @@
package edu.najah.cap.activity;
+import edu.najah.cap.exceptions.BadRequestException;
+import edu.najah.cap.exceptions.NotFoundException;
+import edu.najah.cap.exceptions.SystemBusyException;
+import edu.najah.cap.exceptions.Util;
+import edu.najah.cap.payment.Transaction;
+
+import java.time.Instant;
import java.util.*;
public class UserActivityService implements IUserActivityService {
@@ -10,12 +17,20 @@ public void addUserActivity(UserActivity userActivity) {
}
@Override
- public List getUserActivity(String userId) {
+ public List getUserActivity(String userId) throws SystemBusyException, BadRequestException, NotFoundException {
+ Util.validateUserName(userId);
+ if (!userActivityMap.containsKey(userId)) {
+ throw new NotFoundException("User does not exist");
+ }
return userActivityMap.get(userId);
}
@Override
- public void removeUserActivity(String userId, String id) {
+ public void removeUserActivity(String userId, String id) throws SystemBusyException, BadRequestException, NotFoundException {
+ Util.validateUserName(userId);
+ if (!userActivityMap.containsKey(userId)) {
+ throw new NotFoundException("User does not exist");
+ }
try {
Thread.sleep(100);
} catch (InterruptedException e) {
diff --git a/src/edu/najah/cap/compress/CompressFactory.java b/src/edu/najah/cap/compress/CompressFactory.java
new file mode 100644
index 0000000..922651c
--- /dev/null
+++ b/src/edu/najah/cap/compress/CompressFactory.java
@@ -0,0 +1,11 @@
+package edu.najah.cap.compress;
+
+public class CompressFactory {
+ public static ICompress getCompressType(CompressType type) {
+ ICompress compressor = null;
+ if (type.equals(CompressType.ZIP)) {
+ compressor = new CompressZIP();
+ }
+ return compressor;
+ }
+ }
diff --git a/src/edu/najah/cap/compress/CompressType.java b/src/edu/najah/cap/compress/CompressType.java
new file mode 100644
index 0000000..0df43ea
--- /dev/null
+++ b/src/edu/najah/cap/compress/CompressType.java
@@ -0,0 +1,5 @@
+package edu.najah.cap.compress;
+
+public enum CompressType {
+ ZIP
+}
diff --git a/src/edu/najah/cap/compress/CompressZIP.java b/src/edu/najah/cap/compress/CompressZIP.java
new file mode 100644
index 0000000..be5fef9
--- /dev/null
+++ b/src/edu/najah/cap/compress/CompressZIP.java
@@ -0,0 +1,52 @@
+package edu.najah.cap.compress;
+
+import edu.najah.cap.exceptions.FileDeletionException;
+
+import java.io.*;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import static edu.najah.cap.logs.MyLogging.log;
+
+public class CompressZIP implements ICompress {
+
+ @Override
+ public void compress(String path, List files) throws IOException {
+ log(Level.INFO, "Compressing to ZIP", "CompressZIP", "compress");
+ String outputPath = path + "UserData.zip";
+ try(ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(outputPath))) {
+ for (String f : files) {
+ try {
+ File file = new File(f);
+ ZipEntry entry = new ZipEntry(file.getName());
+ zipOutputStream.putNextEntry(entry);
+ if (!file.exists()) {
+ throw new FileNotFoundException("File not found: " + f);
+ }
+ try (FileInputStream fileInputStream = new FileInputStream(file)) {
+ int len;
+ byte[] data = new byte[1024];
+ while ((len = fileInputStream.read(data)) != -1) {
+ zipOutputStream.write(data, 0, len);
+ }
+ } catch (IOException e) {
+ log(Level.SEVERE, e.getMessage(), "CompressZIP", "compress");
+ } finally {
+ zipOutputStream.closeEntry();
+ }
+ try {
+ if (!file.delete()) {
+ throw new FileDeletionException("File Deletion Failed");
+ }
+ } catch (FileDeletionException e) {
+ log(Level.SEVERE, e.getMessage(), "CompressZIP", "compress");
+ }
+ }catch (NullPointerException e){
+ }
+ }
+ log(Level.INFO, "Compressing Completed", "CompressZIP", "compress");
+ }
+ }
+ }
\ No newline at end of file
diff --git a/src/edu/najah/cap/compress/ICompress.java b/src/edu/najah/cap/compress/ICompress.java
new file mode 100644
index 0000000..98d5c2a
--- /dev/null
+++ b/src/edu/najah/cap/compress/ICompress.java
@@ -0,0 +1,9 @@
+package edu.najah.cap.compress;
+
+import java.io.IOException;
+import java.util.List;
+
+public interface ICompress {
+ public void compress(String path, List files) throws IOException;
+
+}
diff --git a/src/edu/najah/cap/convertor/PDFConvertor.java b/src/edu/najah/cap/convertor/PDFConvertor.java
new file mode 100644
index 0000000..ac6014b
--- /dev/null
+++ b/src/edu/najah/cap/convertor/PDFConvertor.java
@@ -0,0 +1,47 @@
+package edu.najah.cap.convertor;
+
+import com.itextpdf.text.Document;
+import com.itextpdf.text.DocumentException;
+import com.itextpdf.text.Paragraph;
+import com.itextpdf.text.pdf.PdfWriter;
+import edu.najah.cap.exceptions.FileDeletionException;
+
+import java.io.*;
+import java.util.logging.Level;
+
+import static edu.najah.cap.logs.MyLogging.log;
+
+public class PDFConvertor {
+ public static String ConvertToPdf(String path) throws IOException {
+ log(Level.INFO, "Converting to PDF", "PDFConvertor", "ConvertTOPdf");
+ String textFile = path;
+ String pdfFile = path.substring(0, path.length() - 4) + ".pdf";
+ try {
+ Document document = new Document();
+ PdfWriter.getInstance(document, new FileOutputStream(pdfFile));
+ document.open();
+ BufferedReader bufferedReader = new BufferedReader(new FileReader(textFile));
+ String line;
+ while ((line = bufferedReader.readLine()) != null) {
+ document.add(new Paragraph(line));
+ }
+ bufferedReader.close();
+ document.close();
+
+ try {
+ File file = new File(textFile);
+ if (!file.delete()) {
+ throw new FileDeletionException("File Deletion Failed");
+ }
+ } catch (FileDeletionException e) {
+ log(Level.SEVERE, e.getMessage(), "PDFConvertor", "ConvertTOPdf");
+ }
+ log(Level.INFO, "Converting Completed", "PDFConvertor", "ConvertTOPdf");
+ return pdfFile;
+ } catch(DocumentException e) {
+ log(Level.SEVERE, e.getMessage(), "PDFConvertor", "ConvertTOPdf");
+ return null;
+ }
+ }
+}
+
diff --git a/src/edu/najah/cap/data/Application.java b/src/edu/najah/cap/data/Application.java
index 548d35d..60fe538 100644
--- a/src/edu/najah/cap/data/Application.java
+++ b/src/edu/najah/cap/data/Application.java
@@ -3,6 +3,16 @@
import edu.najah.cap.activity.IUserActivityService;
import edu.najah.cap.activity.UserActivity;
import edu.najah.cap.activity.UserActivityService;
+import edu.najah.cap.delete.DeleteFactory;
+import edu.najah.cap.delete.DeleteTypes;
+import edu.najah.cap.delete.IDelete;
+import edu.najah.cap.exceptions.BadRequestException;
+import edu.najah.cap.exceptions.NotFoundException;
+import edu.najah.cap.exceptions.SystemBusyException;
+import edu.najah.cap.exceptions.Util;
+import edu.najah.cap.export.ExportFactory;
+import edu.najah.cap.export.ExportType;
+import edu.najah.cap.export.IExport;
import edu.najah.cap.iam.IUserService;
import edu.najah.cap.iam.UserProfile;
import edu.najah.cap.iam.UserService;
@@ -13,8 +23,15 @@
import edu.najah.cap.posts.IPostService;
import edu.najah.cap.posts.Post;
import edu.najah.cap.posts.PostService;
+import edu.najah.cap.servicesfactories.UserServiceFactory;
+import edu.najah.cap.servicesfactories.UserServiceTypes;
+import java.io.IOException;
import java.time.Instant;
+import java.util.Scanner;
+import java.util.logging.Level;
+
+import static edu.najah.cap.logs.MyLogging.log;
public class Application {
@@ -23,29 +40,75 @@ public class Application {
private static final IUserService userService = new UserService();
private static final IPostService postService = new PostService();
+ private static String loginUserName;
- public static void main(String[] args) {
+ public static void main(String[] args) throws IOException {
generateRandomData();
Instant start = Instant.now();
System.out.println("Application Started: " + start);
+ Scanner scanner = new Scanner(System.in);
+ System.out.println("Enter your username: ");
+ System.out.println("Note: You can use any of the following usernames: user0, user1, user2, user3, .... user99");
+ String userName = scanner.nextLine();
+ setLoginUserName(userName);
//TODO Your application starts here. Do not Change the existing code
+ // This is the path where the exported data will be stored
+ String path = "src/edu/najah/cap/output/";
+ try {
+ IUserService proxyUserService = UserServiceFactory.getUserService(UserServiceTypes.USER_SERVICE_PROXY);
+
+ // Check if username is available before going further
+ while (true) {
+ try {
+ proxyUserService.getUser(userName);
+ break;
+ } catch (NotFoundException e) {
+ log(Level.SEVERE, e.getMessage(), "Application", "main");
+ return;
+ } catch (SystemBusyException e) {
+ log(Level.WARNING, "System Busy, Trying Again...", "Application", "main");
+ } catch (BadRequestException e) {
+ log(Level.SEVERE, e.getMessage(), "Application", "main");
+ return;
+ }
+ }
+ // Export UserData Locally
+ IExport export = ExportFactory.getExportType(ExportType.LOCALLY);
+ export.exportData(userName, path);
+ // Soft Delete
+ IDelete softDelete = DeleteFactory.getDelete(DeleteTypes.SOFT_DELETE);
+ softDelete.delete(userName);
+ // Hard Delete
+ IDelete hardDelete = DeleteFactory.getDelete(DeleteTypes.HARD_DELETE);
+ hardDelete.delete(userName);
+ // Test if username is unavailable after hard delete
+ UserProfile user = new UserProfile();
+ user.setUserName(userName);
+ proxyUserService.addUser(user); // This should throw an exception
+ } catch (Exception e) {
+ log(Level.SEVERE, e.getMessage(), "Application", "main");
+ }
//TODO Your application ends here. Do not Change the existing code
Instant end = Instant.now();
System.out.println("Application Ended: " + end);
+ System.out.println("Total Time: " + (end.toEpochMilli() - start.toEpochMilli()) + " Milliseconds");
}
+
+
private static void generateRandomData() {
+ Util.setSkipValidation(true);
for (int i = 0; i < 100; i++) {
generateUser(i);
generatePost(i);
@@ -53,17 +116,32 @@ private static void generateRandomData() {
generateActivity(i);
}
System.out.println("Data Generation Completed");
+ Util.setSkipValidation(false);
}
+
private static void generateActivity(int i) {
for (int j = 0; j < 100; j++) {
+ try {
+ if(UserType.NEW_USER.equals(userService.getUser("user" + i).getUserType())) {
+ continue;
+ }
+ } catch (Exception e) {
+ System.err.println("Error while generating activity for user" + i);
+ }
userActivityService.addUserActivity(new UserActivity("user" + i, "activity" + i + "." + j, Instant.now().toString()));
}
}
private static void generatePayment(int i) {
for (int j = 0; j < 100; j++) {
- paymentService.pay(new Transaction("user" + i, i * j, "description" + i + "." + j));
+ try {
+ if (userService.getUser("user" + i).getUserType() == UserType.PREMIUM_USER) {
+ paymentService.pay(new Transaction("user" + i, i * j, "description" + i + "." + j));
+ }
+ } catch (Exception e) {
+ System.err.println("Error while generating post for user" + i);
+ }
}
}
@@ -102,4 +180,12 @@ private static UserType getRandomUserType(int i) {
return UserType.PREMIUM_USER;
}
}
+
+ public static String getLoginUserName() {
+ return loginUserName;
+ }
+
+ private static void setLoginUserName(String loginUserName) {
+ Application.loginUserName = loginUserName;
+ }
}
diff --git a/src/edu/najah/cap/delete/DeleteFactory.java b/src/edu/najah/cap/delete/DeleteFactory.java
new file mode 100644
index 0000000..365209b
--- /dev/null
+++ b/src/edu/najah/cap/delete/DeleteFactory.java
@@ -0,0 +1,15 @@
+package edu.najah.cap.delete;
+
+public class DeleteFactory {
+ public static IDelete getDelete(DeleteTypes type) throws IllegalArgumentException{
+ if (DeleteTypes.HARD_DELETE.equals(type)){
+ return new HardDelete();
+ }
+ else if (DeleteTypes.SOFT_DELETE.equals(type)){
+ return new SoftDelete();
+ }
+ else{
+ throw new IllegalArgumentException("Invalid delete type");
+ }
+ }
+}
diff --git a/src/edu/najah/cap/delete/DeleteIterator.java b/src/edu/najah/cap/delete/DeleteIterator.java
new file mode 100644
index 0000000..1a92c3a
--- /dev/null
+++ b/src/edu/najah/cap/delete/DeleteIterator.java
@@ -0,0 +1,39 @@
+ package edu.najah.cap.delete;
+
+ import java.util.Iterator;
+ import java.util.List;
+
+ public class DeleteIterator implements Iterator {
+ private final List list;
+ private int currentIndex = 0;
+
+ public DeleteIterator(List list) throws IllegalArgumentException{
+ if (list == null) {
+ throw new IllegalArgumentException("List cannot be null");
+ }
+ this.list = list;;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return currentIndex < list.size();
+ }
+
+ public void deleteCurrent() {
+ if (currentIndex >= 0 && currentIndex < list.size()) {
+ list.remove(currentIndex);
+ }
+ }
+
+ public boolean isDataFound() {
+ if (list == null) {
+ return false;
+ }
+ return list.size() > 0;
+ }
+
+ @Override
+ public T next() {
+ return list.get(currentIndex++);
+ }
+ }
\ No newline at end of file
diff --git a/src/edu/najah/cap/delete/DeleteService.java b/src/edu/najah/cap/delete/DeleteService.java
new file mode 100644
index 0000000..cba2208
--- /dev/null
+++ b/src/edu/najah/cap/delete/DeleteService.java
@@ -0,0 +1,73 @@
+package edu.najah.cap.delete;
+
+import edu.najah.cap.activity.IUserActivityService;
+import edu.najah.cap.exceptions.BadRequestException;
+import edu.najah.cap.exceptions.NotFoundException;
+import edu.najah.cap.exceptions.SystemBusyException;
+import edu.najah.cap.iam.IUserService;
+import edu.najah.cap.payment.IPayment;
+import edu.najah.cap.posts.IPostService;
+import edu.najah.cap.servicesfactories.*;
+
+import java.security.InvalidParameterException;
+import java.util.logging.Level;
+
+import static edu.najah.cap.logs.MyLogging.log;
+
+public class DeleteService {
+
+ public static synchronized void deleteData(String dataType, String username) throws BadRequestException {
+ try {
+ DeleteIterator iterator = getIterator(dataType, username);
+ if (!iterator.hasNext()) {
+ throw new NotFoundException("No " + dataType + " Found for username: " + username);
+ }
+ while (iterator.hasNext()) {
+ iterator.deleteCurrent();
+ }
+ log(Level.INFO, "All " + dataType + " Deleted for username: " + username, "DeleteService", "deleteData");
+ } catch (NotFoundException e) {
+ log(Level.INFO, "No " + dataType + " Found for username: " + username, "DeleteService", "deleteData");
+ } catch (IllegalArgumentException e) {
+ log(Level.SEVERE, e.getMessage(), "DeleteService", "deleteData");
+ }
+ }
+
+
+ public static synchronized void deleteUser(String username) throws BadRequestException {
+ while (true) {
+ try {
+ IUserService userService = UserServiceFactory.getUserService(UserServiceTypes.USER_SERVICE_PROXY);
+ userService.deleteUser(username);
+ log(Level.INFO, "User Deleted: " + username, "DeleteService", "deleteUser");
+ return;
+ } catch (NotFoundException e) {
+ log(Level.INFO, "User Not Found: " + username, "DeleteService", "deleteUser");
+ return;
+ } catch (SystemBusyException e) {
+ log(Level.WARNING, "System Busy, Trying Again...", "DeleteService", "deleteUser");
+ }
+ }
+ }
+
+ private static DeleteIterator getIterator(String dataType, String username) throws NotFoundException, BadRequestException, IllegalArgumentException {
+ while (true) {
+ try {
+ if ("Posts".equals(dataType)) {
+ IPostService postService = PostServiceFactory.getPostService(PostServiceTypes.POST_SERVICE);
+ return new DeleteIterator<>(postService.getPosts(username));
+ } else if ("Transactions".equals(dataType)) {
+ IPayment paymentService = PaymentServiceFactory.getPaymentService(PaymentServiceTypes.PAYMENT_SERVICE);
+ return new DeleteIterator<>(paymentService.getTransactions(username));
+ } else if ("User Activities".equals(dataType)) {
+ IUserActivityService userActivityService = ActivityServiceFactory.getActivityService(ActivityServiceTypes.ACTIVITY_SERVICE);
+ return new DeleteIterator<>(userActivityService.getUserActivity(username));
+ } else {
+ throw new InvalidParameterException("Invalid Service Type");
+ }
+ } catch (SystemBusyException e) {
+ log(Level.WARNING, "System Busy, Trying Again...", "DeleteService", "getIterator");
+ }
+ }
+ }
+}
diff --git a/src/edu/najah/cap/delete/DeleteTypes.java b/src/edu/najah/cap/delete/DeleteTypes.java
new file mode 100644
index 0000000..d1892a3
--- /dev/null
+++ b/src/edu/najah/cap/delete/DeleteTypes.java
@@ -0,0 +1,6 @@
+package edu.najah.cap.delete;
+
+public enum DeleteTypes {
+ HARD_DELETE,
+ SOFT_DELETE
+}
diff --git a/src/edu/najah/cap/delete/DeletedUsersArchive.java b/src/edu/najah/cap/delete/DeletedUsersArchive.java
new file mode 100644
index 0000000..1ffaa5d
--- /dev/null
+++ b/src/edu/najah/cap/delete/DeletedUsersArchive.java
@@ -0,0 +1,16 @@
+package edu.najah.cap.delete;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DeletedUsersArchive {
+ private static List deletedUsers = new ArrayList<>();
+
+ public static void addDeletedUser(String username) {
+ deletedUsers.add(username);
+ }
+
+ public static boolean isUserDeleted(String username) {
+ return deletedUsers.contains(username);
+ }
+}
\ No newline at end of file
diff --git a/src/edu/najah/cap/delete/HardDelete.java b/src/edu/najah/cap/delete/HardDelete.java
new file mode 100644
index 0000000..b0786d7
--- /dev/null
+++ b/src/edu/najah/cap/delete/HardDelete.java
@@ -0,0 +1,21 @@
+package edu.najah.cap.delete;
+
+import edu.najah.cap.exceptions.BadRequestException;
+
+import java.util.logging.Level;
+
+import static edu.najah.cap.delete.DeleteService.deleteData;
+import static edu.najah.cap.delete.DeleteService.deleteUser;
+import static edu.najah.cap.logs.MyLogging.log;
+
+public class HardDelete implements IDelete {
+ @Override
+ public void delete(String username) throws BadRequestException {
+ log(Level.INFO, "Hard Delete Started for " + username, "HardDelete", "delete");
+ deleteData("Posts", username);
+ deleteData("Transactions", username);
+ deleteData("User Activities", username);
+ deleteUser(username);
+ log(Level.INFO, "Hard Delete Completed for " + username, "HardDelete", "delete");
+ }
+}
diff --git a/src/edu/najah/cap/delete/IDelete.java b/src/edu/najah/cap/delete/IDelete.java
new file mode 100644
index 0000000..885a487
--- /dev/null
+++ b/src/edu/najah/cap/delete/IDelete.java
@@ -0,0 +1,8 @@
+package edu.najah.cap.delete;
+
+import edu.najah.cap.exceptions.BadRequestException;
+
+public interface IDelete {
+ public abstract void delete(String username) throws BadRequestException;
+}
+
diff --git a/src/edu/najah/cap/delete/SoftDelete.java b/src/edu/najah/cap/delete/SoftDelete.java
new file mode 100644
index 0000000..1cbad8a
--- /dev/null
+++ b/src/edu/najah/cap/delete/SoftDelete.java
@@ -0,0 +1,19 @@
+package edu.najah.cap.delete;
+
+import edu.najah.cap.exceptions.BadRequestException;
+
+import java.util.logging.Level;
+
+import static edu.najah.cap.delete.DeleteService.deleteData;
+import static edu.najah.cap.logs.MyLogging.log;
+
+public class SoftDelete implements IDelete {
+ @Override
+ public void delete(String username) throws BadRequestException {
+ log(Level.INFO, "Soft Delete Started for " + username, "SoftDelete", "delete");
+ deleteData("Posts", username);
+ deleteData("Transactions", username);
+ deleteData("User Activities", username);
+ log(Level.INFO, "Soft Delete Completed for " + username, "SoftDelete", "delete");
+ }
+}
diff --git a/src/edu/najah/cap/exceptions/BadRequestException.java b/src/edu/najah/cap/exceptions/BadRequestException.java
new file mode 100644
index 0000000..8cfefac
--- /dev/null
+++ b/src/edu/najah/cap/exceptions/BadRequestException.java
@@ -0,0 +1,7 @@
+package edu.najah.cap.exceptions;
+
+public class BadRequestException extends Exception {
+ public BadRequestException(String message) {
+ super(message);
+ }
+}
diff --git a/src/edu/najah/cap/exceptions/BlankUsernameException.java b/src/edu/najah/cap/exceptions/BlankUsernameException.java
new file mode 100644
index 0000000..c8f24ea
--- /dev/null
+++ b/src/edu/najah/cap/exceptions/BlankUsernameException.java
@@ -0,0 +1,7 @@
+package edu.najah.cap.exceptions;
+
+public class BlankUsernameException extends Exception {
+ public BlankUsernameException(String message) {
+ super(message);
+ }
+}
diff --git a/src/edu/najah/cap/exceptions/FileDeletionException.java b/src/edu/najah/cap/exceptions/FileDeletionException.java
new file mode 100644
index 0000000..f79b17b
--- /dev/null
+++ b/src/edu/najah/cap/exceptions/FileDeletionException.java
@@ -0,0 +1,7 @@
+package edu.najah.cap.exceptions;
+
+public class FileDeletionException extends Exception{
+ public FileDeletionException(String message) {
+ super(message);
+ }
+}
diff --git a/src/edu/najah/cap/exceptions/NotFoundException.java b/src/edu/najah/cap/exceptions/NotFoundException.java
new file mode 100644
index 0000000..6a2a52a
--- /dev/null
+++ b/src/edu/najah/cap/exceptions/NotFoundException.java
@@ -0,0 +1,7 @@
+package edu.najah.cap.exceptions;
+
+public class NotFoundException extends Exception {
+ public NotFoundException(String message) {
+ super(message);
+ }
+}
diff --git a/src/edu/najah/cap/exceptions/SystemBusyException.java b/src/edu/najah/cap/exceptions/SystemBusyException.java
new file mode 100644
index 0000000..4b3a0b9
--- /dev/null
+++ b/src/edu/najah/cap/exceptions/SystemBusyException.java
@@ -0,0 +1,7 @@
+package edu.najah.cap.exceptions;
+
+public class SystemBusyException extends Exception {
+ public SystemBusyException(String message) {
+ super(message);
+ }
+}
diff --git a/src/edu/najah/cap/exceptions/UnqualifiedUserException.java b/src/edu/najah/cap/exceptions/UnqualifiedUserException.java
new file mode 100644
index 0000000..679a353
--- /dev/null
+++ b/src/edu/najah/cap/exceptions/UnqualifiedUserException.java
@@ -0,0 +1,7 @@
+package edu.najah.cap.exceptions;
+
+public class UnqualifiedUserException extends Exception{
+ public UnqualifiedUserException(String message) {
+ super(message);
+ }
+}
diff --git a/src/edu/najah/cap/exceptions/UserAlreadyExistsException.java b/src/edu/najah/cap/exceptions/UserAlreadyExistsException.java
new file mode 100644
index 0000000..420a220
--- /dev/null
+++ b/src/edu/najah/cap/exceptions/UserAlreadyExistsException.java
@@ -0,0 +1,7 @@
+package edu.najah.cap.exceptions;
+
+public class UserAlreadyExistsException extends Exception{
+ public UserAlreadyExistsException(String message) {
+ super(message);
+ }
+}
diff --git a/src/edu/najah/cap/exceptions/UserDeletedException.java b/src/edu/najah/cap/exceptions/UserDeletedException.java
new file mode 100644
index 0000000..6a3eb56
--- /dev/null
+++ b/src/edu/najah/cap/exceptions/UserDeletedException.java
@@ -0,0 +1,7 @@
+package edu.najah.cap.exceptions;
+
+public class UserDeletedException extends Exception{
+ public UserDeletedException(String message) {
+ super(message);
+ }
+}
diff --git a/src/edu/najah/cap/exceptions/Util.java b/src/edu/najah/cap/exceptions/Util.java
new file mode 100644
index 0000000..3c2fedf
--- /dev/null
+++ b/src/edu/najah/cap/exceptions/Util.java
@@ -0,0 +1,30 @@
+package edu.najah.cap.exceptions;
+
+import java.time.Instant;
+
+public class Util {
+ private Util() {
+ }
+ private static boolean skipValidation = false;
+ public static void validateUserName(String userName) throws SystemBusyException, BadRequestException {
+ if (skipValidation) {
+ return;
+ }
+ if (userName == null || userName.isEmpty()) {
+ throw new BadRequestException("User name is required");
+ }
+ if (userName.length() < 4) {
+ throw new BadRequestException("User name must be at least 4 characters");
+ }
+ if (!userName.startsWith("user")) {
+ throw new BadRequestException("User name must start with 'user'");
+ }
+ if (Instant.now().getEpochSecond() % 3 == 0) {
+ throw new SystemBusyException("Something went wrong");
+ }
+
+ }
+ public static void setSkipValidation(boolean skipValidation) {
+ Util.skipValidation = skipValidation;
+ }
+}
diff --git a/src/edu/najah/cap/export/ExportDownload.java b/src/edu/najah/cap/export/ExportDownload.java
new file mode 100644
index 0000000..38dadfb
--- /dev/null
+++ b/src/edu/najah/cap/export/ExportDownload.java
@@ -0,0 +1,33 @@
+package edu.najah.cap.export;
+
+import edu.najah.cap.compress.CompressFactory;
+import edu.najah.cap.compress.CompressType;
+import edu.najah.cap.export.exportservices.ExportServiceFactory;
+import edu.najah.cap.export.exportservices.ExportServiceType;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+
+import static edu.najah.cap.logs.MyLogging.log;
+
+public class ExportDownload implements IExport{
+ public void exportData(String username, String path) {
+ log(Level.INFO, "Exporting " + username + " data to " + path, "ExportDownload", "exportData");
+ try {
+ List files = new ArrayList<>();
+
+ files.add(ExportServiceFactory.getExportService(ExportServiceType.POST).exportData(username, path));
+ files.add(ExportServiceFactory.getExportService(ExportServiceType.ACTIVITY).exportData(username, path));
+ files.add(ExportServiceFactory.getExportService(ExportServiceType.PROFILE).exportData(username, path));
+ files.add(ExportServiceFactory.getExportService(ExportServiceType.TRANSACTION).exportData(username, path));
+
+ CompressFactory.getCompressType(CompressType.ZIP).compress(path, files);
+ } catch (FileNotFoundException e) {
+ log(Level.SEVERE, e.getMessage(), "ExportDownload", "exportData");
+ } catch (Exception e) {
+ log(Level.SEVERE, e.getMessage(), "ExportDownload", "exportData");
+ }
+ }
+}
diff --git a/src/edu/najah/cap/export/ExportFactory.java b/src/edu/najah/cap/export/ExportFactory.java
new file mode 100644
index 0000000..bff7e35
--- /dev/null
+++ b/src/edu/najah/cap/export/ExportFactory.java
@@ -0,0 +1,12 @@
+package edu.najah.cap.export;
+
+public class ExportFactory {
+ public static IExport getExportType(ExportType type) {
+ if (type.equals(ExportType.LOCALLY)){
+ return new ExportDownload();
+ } else if (type.equals(ExportType.UPLOAD)) {
+ return new ExportUpload();
+ }
+ return null;
+ }
+}
diff --git a/src/edu/najah/cap/export/ExportType.java b/src/edu/najah/cap/export/ExportType.java
new file mode 100644
index 0000000..f2942fb
--- /dev/null
+++ b/src/edu/najah/cap/export/ExportType.java
@@ -0,0 +1,5 @@
+package edu.najah.cap.export;
+
+public enum ExportType {
+ LOCALLY, UPLOAD
+}
diff --git a/src/edu/najah/cap/export/ExportUpload.java b/src/edu/najah/cap/export/ExportUpload.java
new file mode 100644
index 0000000..f172342
--- /dev/null
+++ b/src/edu/najah/cap/export/ExportUpload.java
@@ -0,0 +1,14 @@
+package edu.najah.cap.export;
+
+import java.util.logging.Level;
+
+import static edu.najah.cap.logs.MyLogging.log;
+
+public class ExportUpload implements IExport{
+ public void exportData(String username, String link) {
+ log(Level.INFO, "Exporting " + username + " data to " + link, "ExportUpload", "exportData");
+
+ // Implementation
+
+ }
+}
diff --git a/src/edu/najah/cap/export/IExport.java b/src/edu/najah/cap/export/IExport.java
new file mode 100644
index 0000000..8406d89
--- /dev/null
+++ b/src/edu/najah/cap/export/IExport.java
@@ -0,0 +1,5 @@
+package edu.najah.cap.export;
+
+public interface IExport {
+ void exportData(String username, String path);
+}
diff --git a/src/edu/najah/cap/export/exportservices/ExportActivity.java b/src/edu/najah/cap/export/exportservices/ExportActivity.java
new file mode 100644
index 0000000..9948183
--- /dev/null
+++ b/src/edu/najah/cap/export/exportservices/ExportActivity.java
@@ -0,0 +1,73 @@
+package edu.najah.cap.export.exportservices;
+
+import edu.najah.cap.activity.IUserActivityService;
+import edu.najah.cap.activity.UserActivity;
+import edu.najah.cap.convertor.PDFConvertor;
+import edu.najah.cap.exceptions.FileDeletionException;
+import edu.najah.cap.exceptions.NotFoundException;
+import edu.najah.cap.exceptions.SystemBusyException;
+import edu.najah.cap.exceptions.UnqualifiedUserException;
+import edu.najah.cap.iam.IUserService;
+import edu.najah.cap.iam.UserType;
+import edu.najah.cap.servicesfactories.ActivityServiceFactory;
+import edu.najah.cap.servicesfactories.ActivityServiceTypes;
+import edu.najah.cap.servicesfactories.UserServiceFactory;
+import edu.najah.cap.servicesfactories.UserServiceTypes;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.logging.Level;
+
+import static edu.najah.cap.logs.MyLogging.log;
+
+public class ExportActivity implements IExportService {
+ @Override
+ public String exportData(String user, String path) throws Exception {
+ log(Level.INFO, "Exporting activity to local storage...", "ExportActivity", "exportActivity");
+ String outputPath = path + user + "-Activity.txt";
+
+ try (PrintWriter activityWriter = new PrintWriter(new FileWriter(outputPath))) {
+ IUserActivityService userActivityService = ActivityServiceFactory.getActivityService(ActivityServiceTypes.ACTIVITY_SERVICE);
+ IUserService userService = UserServiceFactory.getUserService(UserServiceTypes.USER_SERVICE);
+ List userActivities = null;
+ UserType userType = null;
+ while(true){
+ try {
+ userType = userService.getUser(user).getUserType();
+ userActivities = userActivityService.getUserActivity(user);
+ break;
+ } catch (SystemBusyException e) {
+ log(Level.WARNING, "System Busy, Trying Again...","ExportActivity", "exportActivity");
+ } catch (NotFoundException e) {
+ if(userType == null){
+ throw new NotFoundException(e.getMessage());
+ }
+ throw new UnqualifiedUserException("User is not qualified for exporting activity");
+ }
+ }
+
+
+ for (UserActivity activity : userActivities) {
+ activityWriter.println("User ID: " + activity.getUserId());
+ activityWriter.println("Activity Type: " + activity.getActivityType());
+ activityWriter.println("Activity Date: " + activity.getActivityDate());
+ activityWriter.println();
+ }
+ activityWriter.close();
+ return PDFConvertor.ConvertToPdf(outputPath);
+ } catch (UnqualifiedUserException e) {
+ log(Level.WARNING, e.getMessage(), "ExportActivity", "exportActivity");
+ try {
+ File file = new File(outputPath);
+ if (!file.delete()) {
+ throw new FileDeletionException("File Deletion Failed");
+ }
+ } catch (FileDeletionException x) {
+ log(Level.SEVERE, x.getMessage(), "PDFConvertor", "ConvertTOPdf");
+ }
+ return null;
+ }
+ }
+}
diff --git a/src/edu/najah/cap/export/exportservices/ExportPost.java b/src/edu/najah/cap/export/exportservices/ExportPost.java
new file mode 100644
index 0000000..7d6189c
--- /dev/null
+++ b/src/edu/najah/cap/export/exportservices/ExportPost.java
@@ -0,0 +1,43 @@
+package edu.najah.cap.export.exportservices;
+
+import edu.najah.cap.convertor.PDFConvertor;
+import edu.najah.cap.posts.IPostService;
+import edu.najah.cap.posts.Post;
+import edu.najah.cap.servicesfactories.PostServiceFactory;
+import edu.najah.cap.servicesfactories.PostServiceTypes;
+
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.logging.Level;
+
+import static edu.najah.cap.logs.MyLogging.log;
+
+public class ExportPost implements IExportService {
+ @Override
+ public String exportData(String user, String path) throws Exception {
+ log(Level.INFO, "Exporting posts to local storage...", "ExportPosts", "exportPosts");
+ String outputPath = path + user + "-Posts.txt";
+ try (PrintWriter postWriter = new PrintWriter(new FileWriter(outputPath))) {
+ IPostService postService = PostServiceFactory.getPostService(PostServiceTypes.POST_SERVICE);
+ List posts = null;
+ while(true){
+ try {
+ posts = postService.getPosts(user);
+ break;
+ } catch (Exception e) {
+ log(Level.WARNING, "System Busy, Trying Again...","ExportPosts", "exportPosts");
+ }
+ }
+ for (Post post : posts) {
+ postWriter.println("Post Title: " + post.getTitle());
+ postWriter.println("Post Body: " + post.getBody());
+ postWriter.println("Post Author: " + post.getAuthor());
+ postWriter.println("Post Date: " + post.getDate());
+ postWriter.println();
+ }
+ postWriter.close();
+ return PDFConvertor.ConvertToPdf(outputPath);
+ }
+ }
+}
diff --git a/src/edu/najah/cap/export/exportservices/ExportProfile.java b/src/edu/najah/cap/export/exportservices/ExportProfile.java
new file mode 100644
index 0000000..8af4fa1
--- /dev/null
+++ b/src/edu/najah/cap/export/exportservices/ExportProfile.java
@@ -0,0 +1,49 @@
+package edu.najah.cap.export.exportservices;
+
+import edu.najah.cap.convertor.PDFConvertor;
+import edu.najah.cap.iam.IUserService;
+import edu.najah.cap.iam.UserProfile;
+import edu.najah.cap.servicesfactories.UserServiceFactory;
+import edu.najah.cap.servicesfactories.UserServiceTypes;
+
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.util.logging.Level;
+
+import static edu.najah.cap.logs.MyLogging.log;
+
+public class ExportProfile implements IExportService {
+ @Override
+ public String exportData(String user, String path) throws Exception {
+ log(Level.INFO, "Exporting profile to local storage...", "ExportProfile", "exportProfile");
+ String outputPath = path + user + "-Profile.txt";
+ try (PrintWriter profileWriter = new PrintWriter(new FileWriter(outputPath))) {
+ IUserService userService = UserServiceFactory.getUserService(UserServiceTypes.USER_SERVICE);
+ UserProfile userProfile = null;
+ while(true){
+ try {
+ userProfile = userService.getUser(user);
+ break;
+ } catch (Exception e) {
+ log(Level.WARNING, "System Busy, Trying Again...","ExportProfile", "exportProfile");
+ }
+ }
+ profileWriter.println("First Name: " + userProfile.getFirstName());
+ profileWriter.println("Last Name: " + userProfile.getLastName());
+ profileWriter.println("Phone Number: " + userProfile.getPhoneNumber());
+ profileWriter.println("Email: " + userProfile.getEmail());
+ profileWriter.println("UserName: " + userProfile.getUserName());
+ profileWriter.println("Password: " + userProfile.getPassword());
+ profileWriter.println("Role: " + userProfile.getRole());
+ profileWriter.println("Department: " + userProfile.getDepartment());
+ profileWriter.println("Organization: " + userProfile.getOrganization());
+ profileWriter.println("Country: " + userProfile.getCountry());
+ profileWriter.println("City: " + userProfile.getCity());
+ profileWriter.println("Street: " + userProfile.getStreet());
+ profileWriter.println("Postal Code: " + userProfile.getPostalCode());
+ profileWriter.println("Building: " + userProfile.getBuilding());
+ profileWriter.close();
+ return PDFConvertor.ConvertToPdf(outputPath);
+ }
+ }
+}
diff --git a/src/edu/najah/cap/export/exportservices/ExportServiceFactory.java b/src/edu/najah/cap/export/exportservices/ExportServiceFactory.java
new file mode 100644
index 0000000..bb0570d
--- /dev/null
+++ b/src/edu/najah/cap/export/exportservices/ExportServiceFactory.java
@@ -0,0 +1,16 @@
+package edu.najah.cap.export.exportservices;
+
+public class ExportServiceFactory {
+ public static IExportService getExportService(ExportServiceType type) {
+ if (type.equals(ExportServiceType.POST)) {
+ return new ExportPost();
+ } else if (type.equals(ExportServiceType.ACTIVITY)) {
+ return new ExportActivity();
+ } else if (type.equals(ExportServiceType.PROFILE)) {
+ return new ExportProfile();
+ } else if (type.equals(ExportServiceType.TRANSACTION)) {
+ return new ExportTransaction();
+ }
+ return null;
+ }
+}
diff --git a/src/edu/najah/cap/export/exportservices/ExportServiceType.java b/src/edu/najah/cap/export/exportservices/ExportServiceType.java
new file mode 100644
index 0000000..fd3b8bd
--- /dev/null
+++ b/src/edu/najah/cap/export/exportservices/ExportServiceType.java
@@ -0,0 +1,5 @@
+package edu.najah.cap.export.exportservices;
+
+public enum ExportServiceType {
+ ACTIVITY, PROFILE, POST, TRANSACTION
+}
diff --git a/src/edu/najah/cap/export/exportservices/ExportTransaction.java b/src/edu/najah/cap/export/exportservices/ExportTransaction.java
new file mode 100644
index 0000000..3069460
--- /dev/null
+++ b/src/edu/najah/cap/export/exportservices/ExportTransaction.java
@@ -0,0 +1,76 @@
+package edu.najah.cap.export.exportservices;
+
+import edu.najah.cap.convertor.PDFConvertor;
+import edu.najah.cap.exceptions.FileDeletionException;
+import edu.najah.cap.exceptions.NotFoundException;
+import edu.najah.cap.exceptions.SystemBusyException;
+import edu.najah.cap.exceptions.UnqualifiedUserException;
+import edu.najah.cap.iam.IUserService;
+import edu.najah.cap.iam.UserType;
+import edu.najah.cap.payment.IPayment;
+import edu.najah.cap.payment.Transaction;
+import edu.najah.cap.servicesfactories.PaymentServiceFactory;
+import edu.najah.cap.servicesfactories.PaymentServiceTypes;
+import edu.najah.cap.servicesfactories.UserServiceFactory;
+import edu.najah.cap.servicesfactories.UserServiceTypes;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.logging.Level;
+
+import static edu.najah.cap.logs.MyLogging.log;
+
+public class ExportTransaction implements IExportService {
+ @Override
+ public String exportData(String user, String path) throws Exception {
+ log(Level.INFO, "Exporting transactions to local storage...", "ExportTransaction", "exportTransaction");
+ String outputPath = path + user + "-Transactions.txt";
+ try (PrintWriter transactionWriter = new PrintWriter(new FileWriter(outputPath))) {
+ IPayment paymentService = PaymentServiceFactory.getPaymentService(PaymentServiceTypes.PAYMENT_SERVICE);
+ IUserService userService = UserServiceFactory.getUserService(UserServiceTypes.USER_SERVICE);
+ transactionWriter.println("Balance: " + paymentService.getBalance(user));
+ transactionWriter.println();
+ List transactions = null;
+ UserType userType = null;
+ while (true) {
+ try {
+ userType = userService.getUser(user).getUserType();
+ transactions = paymentService.getTransactions(user);
+ break;
+ } catch (SystemBusyException e) {
+ log(Level.WARNING, "System Busy, Trying Again...", "ExportTransaction", "exportTransaction");
+ } catch (NotFoundException e) {
+ if(userType == null){
+ throw new NotFoundException(e.getMessage());
+ }
+ throw new UnqualifiedUserException("User is not qualified for exporting transactions");
+ }
+ }
+ if (userType == UserType.NEW_USER) {
+ throw new UnqualifiedUserException("User is not qualified to export transactions");
+ }
+ for (Transaction transaction : transactions) {
+ transactionWriter.println("User Name: " + transaction.getUserName());
+ transactionWriter.println("Amount: " + transaction.getAmount());
+ transactionWriter.println("Description: " + transaction.getDescription());
+ transactionWriter.println();
+ }
+ transactionWriter.close();
+ return PDFConvertor.ConvertToPdf(outputPath);
+ } catch (UnqualifiedUserException e) {
+ log(Level.WARNING, e.getMessage(), "ExportTransaction", "exportTransaction");
+ try {
+ File file = new File(outputPath);
+ if (!file.delete()) {
+ throw new FileDeletionException("File Deletion Failed");
+ }
+ } catch (FileDeletionException x) {
+ log(Level.SEVERE, x.getMessage(), "PDFConvertor", "ConvertTOPdf");
+ }
+ return null;
+ }
+
+ }
+}
diff --git a/src/edu/najah/cap/export/exportservices/IExportService.java b/src/edu/najah/cap/export/exportservices/IExportService.java
new file mode 100644
index 0000000..f61aeca
--- /dev/null
+++ b/src/edu/najah/cap/export/exportservices/IExportService.java
@@ -0,0 +1,5 @@
+package edu.najah.cap.export.exportservices;
+
+public interface IExportService {
+ public String exportData(String username, String path) throws Exception;
+}
diff --git a/src/edu/najah/cap/iam/IUserService.java b/src/edu/najah/cap/iam/IUserService.java
index 4101097..3940d3f 100644
--- a/src/edu/najah/cap/iam/IUserService.java
+++ b/src/edu/najah/cap/iam/IUserService.java
@@ -1,8 +1,12 @@
package edu.najah.cap.iam;
+import edu.najah.cap.exceptions.BadRequestException;
+import edu.najah.cap.exceptions.NotFoundException;
+import edu.najah.cap.exceptions.SystemBusyException;
+
public interface IUserService {
void addUser(UserProfile user);
- void updateUser(UserProfile user);
- void deleteUser(String userName);
- UserProfile getUser(String userName);
+ void updateUser(UserProfile user) throws NotFoundException, SystemBusyException, BadRequestException;
+ void deleteUser(String userName) throws NotFoundException, SystemBusyException, BadRequestException;
+ UserProfile getUser(String userName) throws NotFoundException, SystemBusyException, BadRequestException;
}
diff --git a/src/edu/najah/cap/iam/UserService.java b/src/edu/najah/cap/iam/UserService.java
index be437e6..d16a70c 100644
--- a/src/edu/najah/cap/iam/UserService.java
+++ b/src/edu/najah/cap/iam/UserService.java
@@ -1,5 +1,10 @@
package edu.najah.cap.iam;
+import edu.najah.cap.exceptions.BadRequestException;
+import edu.najah.cap.exceptions.NotFoundException;
+import edu.najah.cap.exceptions.SystemBusyException;
+import edu.najah.cap.exceptions.Util;
+
import java.util.HashMap;
import java.util.Map;
@@ -13,17 +18,29 @@ public void addUser(UserProfile user) {
}
@Override
- public void updateUser(UserProfile user) {
+ public void updateUser(UserProfile user) throws NotFoundException, SystemBusyException, BadRequestException {
+ Util.validateUserName(user.getUserName());
+ if (!users.containsKey(user.getUserName())) {
+ throw new NotFoundException("User does not exist");
+ }
users.put(user.getUserName(), user);
}
@Override
- public void deleteUser(String userName) {
+ public void deleteUser(String userName) throws NotFoundException, SystemBusyException, BadRequestException {
+ Util.validateUserName(userName);
+ if (!users.containsKey(userName)) {
+ throw new NotFoundException("User does not exist");
+ }
users.remove(userName);
}
@Override
- public UserProfile getUser(String userName) {
+ public UserProfile getUser(String userName) throws NotFoundException, SystemBusyException, BadRequestException {
+ Util.validateUserName(userName);
+ if (!users.containsKey(userName)) {
+ throw new NotFoundException("User does not exist");
+ }
return users.get(userName);
}
}
diff --git a/src/edu/najah/cap/logs/MyLogging.java b/src/edu/najah/cap/logs/MyLogging.java
new file mode 100644
index 0000000..df8c8db
--- /dev/null
+++ b/src/edu/najah/cap/logs/MyLogging.java
@@ -0,0 +1,32 @@
+package edu.najah.cap.logs;
+
+import java.io.IOException;
+import java.util.logging.FileHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.SimpleFormatter;
+
+public class MyLogging {
+ private static Logger logger;
+ private static FileHandler fileHandler;
+
+ static {
+ try {
+ logger = Logger.getLogger(MyLogging.class.getName());
+ fileHandler = new FileHandler("./out/production/AdvancedProjectTeam15/edu/najah/cap/logs/logs.log");
+ logger.addHandler(fileHandler);
+ SimpleFormatter formatter = new SimpleFormatter();
+ fileHandler.setFormatter(formatter);
+ } catch (SecurityException | IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static Logger getLogger() {
+ return logger;
+ }
+
+ public static void log(Level level, String msg, String className, String methodName) {
+ getLogger().logp(level, className, methodName, msg);
+ }
+}
diff --git a/src/edu/najah/cap/payment/IPayment.java b/src/edu/najah/cap/payment/IPayment.java
index c5ff072..7bc0a10 100644
--- a/src/edu/najah/cap/payment/IPayment.java
+++ b/src/edu/najah/cap/payment/IPayment.java
@@ -1,10 +1,14 @@
package edu.najah.cap.payment;
+import edu.najah.cap.exceptions.BadRequestException;
+import edu.najah.cap.exceptions.NotFoundException;
+import edu.najah.cap.exceptions.SystemBusyException;
+
import java.util.List;
public interface IPayment {
void pay(Transaction transaction);
double getBalance(String userName);
- void removeTransaction(String userName, String id);
- List getTransactions(String userName);
+ void removeTransaction(String userName, String id) throws SystemBusyException, BadRequestException, NotFoundException;
+ List getTransactions(String userName) throws SystemBusyException, BadRequestException, NotFoundException;
}
diff --git a/src/edu/najah/cap/payment/PaymentService.java b/src/edu/najah/cap/payment/PaymentService.java
index da6e3d5..6069481 100644
--- a/src/edu/najah/cap/payment/PaymentService.java
+++ b/src/edu/najah/cap/payment/PaymentService.java
@@ -1,5 +1,10 @@
package edu.najah.cap.payment;
+import edu.najah.cap.exceptions.BadRequestException;
+import edu.najah.cap.exceptions.NotFoundException;
+import edu.najah.cap.exceptions.SystemBusyException;
+import edu.najah.cap.exceptions.Util;
+
import java.util.*;
public class PaymentService implements IPayment {
@@ -20,12 +25,16 @@ public double getBalance(String userName) {
}
@Override
- public void removeTransaction(String userName, String id) {
+ public void removeTransaction(String userName, String id) throws SystemBusyException, BadRequestException, NotFoundException {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
+ Util.validateUserName(userName);
+ if (!transactionMap.containsKey(userName)) {
+ throw new NotFoundException("User does not exist");
+ }
Iterator iterator = transactionMap.get(userName).iterator();
while (iterator.hasNext()) {
Transaction transaction = iterator.next();
@@ -37,7 +46,11 @@ public void removeTransaction(String userName, String id) {
}
@Override
- public List getTransactions(String userName) {
+ public List getTransactions(String userName) throws SystemBusyException, BadRequestException, NotFoundException {
+ Util.validateUserName(userName);
+ if (!transactionMap.containsKey(userName)) {
+ throw new NotFoundException("User does not exist");
+ }
return transactionMap.get(userName);
}
diff --git a/src/edu/najah/cap/posts/IPostService.java b/src/edu/najah/cap/posts/IPostService.java
index b00a83d..4f64a04 100644
--- a/src/edu/najah/cap/posts/IPostService.java
+++ b/src/edu/najah/cap/posts/IPostService.java
@@ -1,11 +1,15 @@
package edu.najah.cap.posts;
+import edu.najah.cap.exceptions.BadRequestException;
+import edu.najah.cap.exceptions.NotFoundException;
+import edu.najah.cap.exceptions.SystemBusyException;
+
import java.util.List;
public interface IPostService {
void addPost(Post post);
- List getPosts(String author);
+ List getPosts(String author) throws SystemBusyException, BadRequestException, NotFoundException;
- void deletePost(String author, String id);
+ void deletePost(String author, String id) throws SystemBusyException, BadRequestException, NotFoundException;
}
diff --git a/src/edu/najah/cap/posts/PostService.java b/src/edu/najah/cap/posts/PostService.java
index 85abe00..63fbd5e 100644
--- a/src/edu/najah/cap/posts/PostService.java
+++ b/src/edu/najah/cap/posts/PostService.java
@@ -1,5 +1,10 @@
package edu.najah.cap.posts;
+import edu.najah.cap.exceptions.BadRequestException;
+import edu.najah.cap.exceptions.NotFoundException;
+import edu.najah.cap.exceptions.SystemBusyException;
+import edu.najah.cap.exceptions.Util;
+
import java.util.*;
public class PostService implements IPostService {
@@ -11,17 +16,25 @@ public void addPost(Post post) {
}
@Override
- public List getPosts(String author) {
+ public List getPosts(String author) throws SystemBusyException, BadRequestException, NotFoundException {
+ Util.validateUserName(author);
+ if (!posts.containsKey(author)) {
+ throw new NotFoundException("User does not exist");
+ }
return posts.get(author);
}
@Override
- public void deletePost(String author, String id) {
+ public void deletePost(String author, String id) throws SystemBusyException, BadRequestException, NotFoundException {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
+ Util.validateUserName(author);
+ if (!posts.containsKey(author)) {
+ throw new NotFoundException("User does not exist");
+ }
List authorPosts = posts.get(author);
if (authorPosts != null) {
Iterator iterator = authorPosts.iterator();
diff --git a/src/edu/najah/cap/proxy/UserServiceProxy.java b/src/edu/najah/cap/proxy/UserServiceProxy.java
new file mode 100644
index 0000000..ab5607d
--- /dev/null
+++ b/src/edu/najah/cap/proxy/UserServiceProxy.java
@@ -0,0 +1,67 @@
+package edu.najah.cap.proxy;
+
+import edu.najah.cap.delete.DeletedUsersArchive;
+import edu.najah.cap.exceptions.*;
+import edu.najah.cap.iam.IUserService;
+import edu.najah.cap.iam.UserProfile;
+import edu.najah.cap.iam.UserService;
+
+import java.util.logging.Level;
+
+import static edu.najah.cap.logs.MyLogging.log;
+
+
+public class UserServiceProxy implements IUserService {
+ private UserService userService;
+
+ public UserServiceProxy() {
+ if (userService == null) {
+ userService = new UserService();
+ }
+ }
+
+ @Override
+ public void addUser(UserProfile user) {
+ try {
+ validateUsername(user.getUserName());
+ } catch (UserDeletedException | BlankUsernameException | UserAlreadyExistsException | BadRequestException e) {
+ log(Level.SEVERE, e.getMessage(), "UserServiceProxy", "addUser");
+ } catch (NotFoundException e) {
+ userService.addUser(user);
+ }
+ }
+
+ @Override
+ public void updateUser(UserProfile user) throws NotFoundException, SystemBusyException, BadRequestException {
+ userService.updateUser(user);
+ }
+
+ @Override
+ public void deleteUser(String userName) throws NotFoundException, SystemBusyException, BadRequestException {
+ DeletedUsersArchive.addDeletedUser(userName);
+ userService.deleteUser(userName);
+ }
+
+ @Override
+ public UserProfile getUser(String userName) throws NotFoundException, SystemBusyException, BadRequestException {
+ return userService.getUser(userName);
+ }
+
+ private void validateUsername(String username) throws BlankUsernameException, UserDeletedException, UserAlreadyExistsException, NotFoundException, BadRequestException {
+
+ if (username.trim().isBlank()) {
+ throw new BlankUsernameException("User name cannot be empty");
+ }
+ if (DeletedUsersArchive.isUserDeleted(username)) {
+ throw new UserDeletedException("Username unavailable as it is deleted");
+ }
+ while (true) {
+ try {
+ userService.getUser(username);
+ throw new UserAlreadyExistsException("User already exists");
+ } catch (SystemBusyException e) {
+ log(Level.WARNING, "System Busy, Trying Again...", "UserServiceProxy", "validateUsername");
+ }
+ }
+ }
+}
diff --git a/src/edu/najah/cap/servicesfactories/ActivityServiceFactory.java b/src/edu/najah/cap/servicesfactories/ActivityServiceFactory.java
new file mode 100644
index 0000000..4c6cda0
--- /dev/null
+++ b/src/edu/najah/cap/servicesfactories/ActivityServiceFactory.java
@@ -0,0 +1,15 @@
+package edu.najah.cap.servicesfactories;
+
+import edu.najah.cap.activity.IUserActivityService;
+import edu.najah.cap.activity.UserActivityService;
+
+public class ActivityServiceFactory {
+ public static IUserActivityService getActivityService(ActivityServiceTypes type) throws IllegalArgumentException{
+ if (ActivityServiceTypes.ACTIVITY_SERVICE.equals(type)) {
+ return new UserActivityService();
+ }
+ else {
+ throw new IllegalArgumentException("Invalid activity service");
+ }
+ }
+}
diff --git a/src/edu/najah/cap/servicesfactories/ActivityServiceTypes.java b/src/edu/najah/cap/servicesfactories/ActivityServiceTypes.java
new file mode 100644
index 0000000..bb4d224
--- /dev/null
+++ b/src/edu/najah/cap/servicesfactories/ActivityServiceTypes.java
@@ -0,0 +1,5 @@
+package edu.najah.cap.servicesfactories;
+
+public enum ActivityServiceTypes {
+ ACTIVITY_SERVICE
+}
diff --git a/src/edu/najah/cap/servicesfactories/PaymentServiceFactory.java b/src/edu/najah/cap/servicesfactories/PaymentServiceFactory.java
new file mode 100644
index 0000000..cf16c37
--- /dev/null
+++ b/src/edu/najah/cap/servicesfactories/PaymentServiceFactory.java
@@ -0,0 +1,15 @@
+package edu.najah.cap.servicesfactories;
+
+import edu.najah.cap.payment.IPayment;
+import edu.najah.cap.payment.PaymentService;
+
+public class PaymentServiceFactory {
+ public static IPayment getPaymentService(PaymentServiceTypes type) throws IllegalArgumentException{
+ if (PaymentServiceTypes.PAYMENT_SERVICE.equals(type)) {
+ return new PaymentService();
+ }
+ else {
+ throw new IllegalArgumentException("Invalid payment service");
+ }
+ }
+}
diff --git a/src/edu/najah/cap/servicesfactories/PaymentServiceTypes.java b/src/edu/najah/cap/servicesfactories/PaymentServiceTypes.java
new file mode 100644
index 0000000..9e3428a
--- /dev/null
+++ b/src/edu/najah/cap/servicesfactories/PaymentServiceTypes.java
@@ -0,0 +1,5 @@
+package edu.najah.cap.servicesfactories;
+
+public enum PaymentServiceTypes {
+ PAYMENT_SERVICE
+}
diff --git a/src/edu/najah/cap/servicesfactories/PostServiceFactory.java b/src/edu/najah/cap/servicesfactories/PostServiceFactory.java
new file mode 100644
index 0000000..7a34237
--- /dev/null
+++ b/src/edu/najah/cap/servicesfactories/PostServiceFactory.java
@@ -0,0 +1,15 @@
+package edu.najah.cap.servicesfactories;
+
+import edu.najah.cap.posts.IPostService;
+import edu.najah.cap.posts.PostService;
+
+public class PostServiceFactory {
+ public static IPostService getPostService(PostServiceTypes type) throws IllegalArgumentException{
+ if (PostServiceTypes.POST_SERVICE.equals(type)) {
+ return new PostService();
+ }
+ else {
+ throw new IllegalArgumentException("Invalid post service");
+ }
+ }
+}
diff --git a/src/edu/najah/cap/servicesfactories/PostServiceTypes.java b/src/edu/najah/cap/servicesfactories/PostServiceTypes.java
new file mode 100644
index 0000000..5040b32
--- /dev/null
+++ b/src/edu/najah/cap/servicesfactories/PostServiceTypes.java
@@ -0,0 +1,5 @@
+package edu.najah.cap.servicesfactories;
+
+public enum PostServiceTypes {
+ POST_SERVICE
+}
diff --git a/src/edu/najah/cap/servicesfactories/UserServiceFactory.java b/src/edu/najah/cap/servicesfactories/UserServiceFactory.java
new file mode 100644
index 0000000..7fb9245
--- /dev/null
+++ b/src/edu/najah/cap/servicesfactories/UserServiceFactory.java
@@ -0,0 +1,19 @@
+package edu.najah.cap.servicesfactories;
+
+import edu.najah.cap.iam.IUserService;
+import edu.najah.cap.iam.UserService;
+import edu.najah.cap.proxy.UserServiceProxy;
+
+public class UserServiceFactory {
+ public static IUserService getUserService(UserServiceTypes type) throws IllegalArgumentException{
+ if (UserServiceTypes.USER_SERVICE.equals(type)) {
+ return new UserService();
+ }
+ if (UserServiceTypes.USER_SERVICE_PROXY.equals(type)) {
+ return new UserServiceProxy();
+ }
+ else {
+ throw new IllegalArgumentException("Invalid user service");
+ }
+ }
+}
diff --git a/src/edu/najah/cap/servicesfactories/UserServiceTypes.java b/src/edu/najah/cap/servicesfactories/UserServiceTypes.java
new file mode 100644
index 0000000..c3cb08d
--- /dev/null
+++ b/src/edu/najah/cap/servicesfactories/UserServiceTypes.java
@@ -0,0 +1,5 @@
+package edu.najah.cap.servicesfactories;
+
+public enum UserServiceTypes {
+ USER_SERVICE, USER_SERVICE_PROXY
+}