Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

11 Networking.Persistence Module with DAO abstract class, implementations and builder #15

Merged
merged 23 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
852a38f
test: add DAOBuilderTest class for testing DAOBuilder functionality
SverreNystad Mar 12, 2024
82363ed
docs: add comprehensive documentation to DAO interface
SverreNystad Mar 13, 2024
cb15146
feat: add DAOBuilder class with CRUD capabilities
SverreNystad Mar 13, 2024
5134707
feat: create DAOFirebase
SverreNystad Mar 13, 2024
b7cf562
feat: create DAOLocal with expected methods
SverreNystad Mar 13, 2024
d00188c
feat: Add can do operation methods to DAO interface
SverreNystad Mar 13, 2024
1954465
feat: add CRUD permissions to DAOLocal class
SverreNystad Mar 13, 2024
bcd2265
feat: add stub method checks for CRUD operations in DAOFirebase class
SverreNystad Mar 13, 2024
1d84f7f
refactor: change name of DAO classes to have DAO as zufix
SverreNystad Mar 13, 2024
dad98b9
test: add tests for DAOBuilder with different capabilities
SverreNystad Mar 13, 2024
fe618d1
test: Update imports in DAOBuilderTest.java
SverreNystad Mar 13, 2024
f1a9891
feat: Change return type of add method in DAO interface
SverreNystad Mar 13, 2024
fc79cd0
test: add DAOTest class for testing DAO CRUD functionality
SverreNystad Mar 13, 2024
9e68997
feat: add MockDAO implementation for in-memory storage
SverreNystad Mar 13, 2024
305b952
refactor: change DAO tp an abstract base class with permission logic
SverreNystad Mar 13, 2024
a05dacb
docs: correct javadocs of DAO
SverreNystad Mar 13, 2024
67325eb
Style: Add missing line breaks in DAO class
SverreNystad Mar 13, 2024
983bd42
build: add Google services plugin and Firebase database dependency
SverreNystad Mar 13, 2024
b308f28
refactor: correct misspelling of persistence in folder name
SverreNystad Mar 13, 2024
9894694
Revert "build: add Google services plugin and Firebase database depen…
SverreNystad Mar 14, 2024
98d4f00
refactor: Make generics order more intuitive in DAO class and DAOBuil…
SverreNystad Mar 14, 2024
9355e33
feat: replace LocalDAO with MockDAO in DAOBuilder
SverreNystad Mar 14, 2024
ebd10cb
refactor: make DAO return optional instead of value that can be null
SverreNystad Mar 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 102 additions & 1 deletion core/src/com/softwarearchitecture/networking/persistence/DAO.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,106 @@
package com.softwarearchitecture.networking.persistence;

public interface DAO {
import java.util.List;
import java.util.Optional;

/**
* Represents a Data Access Object (DAO), following the Data Access Object pattern.
* This abstract base class abstracts the interaction with the data storage system, allowing for operations
* on stored data without exposing the details of the implementation. It provides a standardized
* method to access, modify, and manage data across different types of storage mechanisms.
*
* @param <K> The type of the primary key used to identify objects of type T.
* @param <T> The type of the object managed by this DAO.
*
* @see <a href="https://en.wikipedia.org/wiki/Data_access_object">Data Access Object on Wikipedia</a>
*/
public abstract class DAO<K, T> {
protected boolean create;
protected boolean read;
protected boolean update;
protected boolean delete;

/**
* Indicates whether this DAO implementation supports the creation (addition) of new instances.
*
* @return {@code true} if the DAO supports creating new instances; {@code false} otherwise.
*/
public boolean canCreate() {
return create;
}

/**
* Indicates whether this DAO implementation supports reading (retrieving) instances.
*
* @return {@code true} if the DAO supports reading instances; {@code false} otherwise.
*/
public boolean canRead() {
return read;
}

/**
* Indicates whether this DAO implementation supports updating existing instances.
*
* @return {@code true} if the DAO supports updating instances; {@code false} otherwise.
*/
public boolean canUpdate() {
return update;
}

/**
* Indicates whether this DAO implementation supports deleting instances.
*
* @return {@code true} if the DAO supports deleting instances; {@code false} otherwise.
*/
public boolean canDelete() {
return delete;
}

/**
* Retrieves all instances of type {@code T} from the data storage.
*
* @return A {@link List} containing all instances of type {@code T} found in the data storage;
* an empty list if no instances are found.
*/
public abstract List<T> loadAll();

/**
* Finds and returns an {@link Optional} wrapper for the instance of type {@code T} identified by the given primary key {@code id}.
*
* This method provides a way to safely access instances without risking a {@code NullPointerException}. If no instance is found
* for the specified {@code id}, an empty {@link Optional} is returned.
*
* @param id The primary key used to identify the instance in the data storage.
* @return An {@link Optional} containing the instance of type {@code T} associated with the specified {@code id}.
* If no such instance exists, an empty {@link Optional} is returned.
*/
public abstract Optional<T> get(K id);

/**
* Updates the instance of type {@code T} identified by the given primary key {@code id} with
* the provided {@code object} data.
*
* @param id The primary key used to identify the instance to be updated.
* @param object The updated instance of type {@code T} to replace the existing one.
* @return {@code true} if the update was successful; {@code false} otherwise.
*/
public abstract boolean update(K id, T object);

/**
* Deletes the instance of type {@code T} identified by the given primary key {@code id}.
*
* @param id The primary key used to identify the instance to be deleted.
* @return {@code true} if the deletion was successful; {@code false} otherwise.
*/
public abstract boolean delete(K id);

/**
* Adds a new instance of type {@code T} to the data storage. If an instance with the same primary key
* already exists, the operation will not proceed.
*
* @param object The instance of type {@code T} to be added to the data storage.
* @return The primary key of the newly added instance; {@code null} if the operation failed.
*/
public abstract K add(T object);

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,84 @@
package com.softwarearchitecture.networking.persistence;

public class DAOBuilder {
/**
* A builder class for creating instances of Data Access Objects ({@link DAO}s) with configurable
* CRUD (Create, Read, Update, Delete) capabilities. This class follows the Builder design pattern
* to allow for configuration of DAO capabilities based on specific application needs.
* <p>
* The builder initializes with all CRUD operations disabled and allows enabling them individually
* through method chaining. The final {@link DAO} instance is created with a call to {@code build()}, which
* returns a {@link DAO} configured as per the builder settings.
* <p>
* Example usage:
* <pre>
* DAO<String, MyEntity> dao = new DAOBuilder<String, MyEntity>().withCreate()
* .withRead()
* .build();
* </pre>
*
* @param <K> The type of the primary key used by the DAO to identify entities.
* @param <T> The type of the entity object managed by the DAO.
*
* @see <a href="https://en.wikipedia.org/wiki/Builder_pattern">Builder pattern on Wikipedia</a>
*/
public class DAOBuilder<K, T>{

private boolean create = false;
private boolean read = false;
private boolean update = false;
private boolean delete = false;

/**
* Enables the creation capability for the DAO being built.
*
* @return This builder instance for method chaining.
*/
public DAOBuilder<K, T> withCreate() {
create = true;
return this;
}

/**
* Enables the read capability for the DAO being built.
*
* @return This builder instance for method chaining.
*/
public DAOBuilder<K, T> withRead() {
read = true;
return this;
}

/**
* Enables the update capability for the DAO being built.
*
* @return This builder instance for method chaining.
*/
public DAOBuilder<K, T> withUpdate() {
update = true;
return this;
}

/**
* Enables the delete capability for the DAO being built.
*
* @return This builder instance for method chaining.
*/
public DAOBuilder<K, T> withDelete() {
delete = true;
return this;
}

/**
* Constructs and returns a DAO instance configured according to the builder settings.
* This method decides the specific DAO implementation to instantiate based on the
* configuration provided. Currently, defaults to {@code DAOLocal}.
*
* @return A configured DAO instance.
*/
public DAO<K, T> build() {
// TODO: add conditional logic to determine which DAO implementation to use
// based on the configuration of system capabilities
DAO<K, T> dao = new MockDAO<K, T>(create, read, update, delete);
return dao;
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.softwarearchitecture.networking.persistence;

import java.util.List;
import java.util.Optional;

public class FirebaseDAO<K, T> extends DAO<K, T> {

public FirebaseDAO(boolean create, boolean read, boolean update, boolean delete) {
this.create = create;
this.read = read;
this.update = update;
this.delete = delete;
}

@Override
public List<T> loadAll() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'loadAll'");
}

@Override
public Optional<T> get(K id) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'get'");
}

@Override
public boolean update(K id, T object) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'update'");
}

@Override
public boolean delete(K id) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'delete'");
}

@Override
public K add(T object) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'add'");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.softwarearchitecture.networking.persistence;

import java.util.List;
import java.util.Optional;

public class LocalDAO<K, T> extends DAO<K, T> {

public LocalDAO(boolean create, boolean read, boolean update, boolean delete) {
this.create = create;
this.read = read;
this.update = update;
this.delete = delete;
}

@Override
public List<T> loadAll() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'loadAll'");
}

@Override
public Optional<T> get(K id) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'get'");
}

@Override
public boolean update(K id, T object) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'update'");
}

@Override
public boolean delete(K id) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'delete'");
}

@Override
public K add(T object) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'add'");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.softwarearchitecture.networking.persistence;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class MockDAO<K, T> extends DAO<K, T>{


public MockDAO(boolean create, boolean read, boolean update, boolean delete) {
this.create = create;
this.read = read;
this.update = update;
this.delete = delete;
}

// In-memory storage for entities, using a Map to simulate database storage.
private Map<K, T> storage = new HashMap<>();

// Simulating key generation.
private Integer nextId = 0;


@Override
public List<T> loadAll() {
return new ArrayList<>(storage.values());
}

@Override
public Optional<T> get(K id) {
Optional<T> result = Optional.ofNullable(storage.get(id));
return result;
}

@Override
public boolean update(K id, T object) {
if (storage.containsKey(id)) {
storage.put(id, object);
return true;
}
return false;
}

@Override
public boolean delete(K id) {
if (storage.containsKey(id)) {
storage.remove(id);
return true;
}
return false;
}

@Override
public K add(T object) {
// Simulating key generation and ensuring type safety via casting.
// This casting is only safe if K is compatible with the type of nextId's value.
@SuppressWarnings("unchecked")
K key = (K) nextId;
this.nextId++;
storage.put(key, object);
return key;
}

}
Loading
Loading