diff --git a/active-record/README.md b/active-record/README.md new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/active-record/etc/active-record.urm.puml b/active-record/etc/active-record.urm.puml new file mode 100644 index 000000000000..d7b98c2734a0 --- /dev/null +++ b/active-record/etc/active-record.urm.puml @@ -0,0 +1,40 @@ +@startuml +package com.iluwatar.activeobject { + class ActiveDatabase { + ~ dbDomain : String + ~ dbName : String + ~ password : String + ~ tableName : String + ~ username : String + + ActiveDatabase(dbName : String, username : String, password : String, dbDomain : String, tableName : String) + + getDbDomain() : String + + getDbName() : String + + getPassword() : String + + getTableName() : String + + getUsername() : String + } + class ActiveRow { + ~ columnCount : int + ~ columns : ArrayList + ~ con : Connection + ~ contents : ArrayList + ~ dataBase : ActiveDatabase + ~ delete : String + ~ id : String + ~ read : String + ~ write : String + + ActiveRow(dataBase : ActiveDatabase, id : String) + + delete() + + initialise() + + read() : ArrayList + + write() + } + class App { + + App() + + main(args : String[]) {static} + } + interface Rowverride { + } +} +ActiveRow --> "-dataBase" ActiveDatabase +@enduml \ No newline at end of file diff --git a/active-record/pom.xml b/active-record/pom.xml new file mode 100644 index 000000000000..9661de1449ab --- /dev/null +++ b/active-record/pom.xml @@ -0,0 +1,49 @@ + + + 4.0.0 + + java-design-patterns + com.iluwatar + 1.26.0-SNAPSHOT + + active-record + + + com.mysql + mysql-connector-j + 8.0.31 + + + org.junit.jupiter + junit-jupiter-engine + test + + + + 15 + 15 + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + active-record + + + + + + + + + + \ No newline at end of file diff --git a/active-record/src/main/java/com/iluwatar/activeobject/ActiveDatabase.java b/active-record/src/main/java/com/iluwatar/activeobject/ActiveDatabase.java new file mode 100644 index 000000000000..0646d43dc98a --- /dev/null +++ b/active-record/src/main/java/com/iluwatar/activeobject/ActiveDatabase.java @@ -0,0 +1,55 @@ +package com.iluwatar.activeobject; + +import java.sql.SQLException; + +/** + * This class initialises frequently needed variables for the MySQLWorkbench Database. + */ +public class ActiveDatabase { + + final String dbDomain; + final String dbName; + final String username; + final String password; + final String tableName; + + /** + * Constructor needed to instantiate the database object which is used with the MySQLWorkbench + * Database. + * + * @param dbName Name of the database as String. + * @param username Username for the database as String. + * @param password Password for the database as String. + * @param dbDomain The domain for the database as String. Tested on localhost:3306 + * @param tableName Name of the table which you wish to create the active row. + */ + public ActiveDatabase(String dbName, String username, String password, String dbDomain, + String tableName) { + this.dbDomain = dbDomain; + this.dbName = dbName; + this.username = username; + this.password = password; + this.tableName = tableName; + } + + public String getDbDomain() { + return dbDomain; + } + + public String getDbName() { + return dbName; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public String getTableName() { + return tableName; + } + +} diff --git a/active-record/src/main/java/com/iluwatar/activeobject/ActiveRow.java b/active-record/src/main/java/com/iluwatar/activeobject/ActiveRow.java new file mode 100644 index 000000000000..24b048583a19 --- /dev/null +++ b/active-record/src/main/java/com/iluwatar/activeobject/ActiveRow.java @@ -0,0 +1,159 @@ +package com.iluwatar.activeobject; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; + +/** + * ActiveRow attempts to implement the fundamental ruby on rails 'Active Record' design pattern in + * Java. + */ +public class ActiveRow { + + String id; + ActiveDatabase dataBase; + Connection con; + String read; + String delete; + String write; + int columnCount; + ArrayList columns; + ArrayList contents = new ArrayList<>(); + + /** + * ActiveRow attempts to implement the fundamental ruby on rails 'Active Record' design pattern in + * Java. + * + * @param dataBase A Database object which handles opening the connection. + * @param id The unique identifier of a row. + */ + public ActiveRow(ActiveDatabase dataBase, String id) { + this.dataBase = dataBase; + this.id = id; + initialise(); + } + + /** + * This initialises the class by creating a connection and populating the column names and other + * variables which are used in the program. + */ + @Rowverride + public void initialise() { + try { + con = DriverManager + .getConnection("jdbc:mysql://" + dataBase.getDbDomain() + "/" + dataBase.getDbName(), + dataBase.getUsername(), dataBase.getPassword()); + } catch (SQLException e) { + e.printStackTrace(); + } + + try { + Statement statement = con.createStatement(); + ResultSet columnSet = statement.executeQuery( + "SELECT * FROM `" + dataBase.getDbName() + "`.`" + dataBase.getTableName() + "`"); + ArrayList columnNames = new ArrayList(); + ResultSetMetaData rsmd = columnSet.getMetaData(); + columnCount = rsmd.getColumnCount(); + for (int i = 1; i < columnCount + 1; i++) { + String name = rsmd.getColumnName(i); + columnNames.add(name); + } + this.columns = columnNames; + read = + "SELECT * FROM `" + dataBase.getDbName() + "`.`" + dataBase.getTableName() + "` WHERE ID=" + + this.id; + delete = "DELETE FROM `" + dataBase.getDbName() + "`.`" + dataBase.getTableName() + "`" + + " WHERE ID = '" + this.id + "';"; + write = "INSERT INTO `" + dataBase.getDbName() + "`.`" + dataBase.getTableName() + "`"; + statement.close(); + columnSet.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + + + } + + /** + * Writes contents of the active row object to the chosen database. + */ + @Rowverride + public void write() { + StringBuilder query = new StringBuilder(); + query.append(write); + query.append(" VALUES ("); + for (String con : this.contents) { + if (contents.indexOf(con) != this.contents.size() - 1) { + query.append("'"); + query.append(con); + query.append("' "); + query.append(","); + } else { + query.append("'"); + query.append(con); + query.append("' "); + query.append(")"); + } + } + + try { + PreparedStatement stmt = con.prepareStatement(query.toString()); + stmt.executeUpdate(); + + } catch (Exception e) { + e.printStackTrace(); + } + + } + + /** + * Deletes the current instance of the active row from the database based on the given ID value. + */ + @Rowverride + public void delete() { + if (this.read().equals(new ArrayList())) { + System.out.println("Row does not exist."); + return; + } + try { + con.prepareStatement(delete).executeUpdate(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Reads the current active row. + * + * @return the current active row contents as Arraylist + */ + @Rowverride + public ArrayList read() { + try { + Statement statement = con.createStatement(); + + ResultSet rowResult = statement.executeQuery(read); + while (rowResult.next()) { + for (int col = 1; col <= columnCount; col++) { + Object value = rowResult.getObject(col); + if (value != null) { + contents.add(value.toString()); + } + } + } + rowResult.close(); + + } catch (Exception e) { + e.printStackTrace(); + } + + return this.contents; + } + +} diff --git a/active-record/src/main/java/com/iluwatar/activeobject/App.java b/active-record/src/main/java/com/iluwatar/activeobject/App.java new file mode 100644 index 000000000000..2266e25a1412 --- /dev/null +++ b/active-record/src/main/java/com/iluwatar/activeobject/App.java @@ -0,0 +1,30 @@ +package com.iluwatar.activeobject; + +import java.util.ArrayList; +import java.util.Arrays; + +/** + * Useful examples of common useage of the program. + */ +public class App { + + /** + * Use this method to become familiar with the program. + * + * @param args arguments passed into the main method. + */ + public static void main(String[] args) { + try { + ActiveDatabase activeDatabase = new ActiveDatabase("world", "root", "apple-trunks", "localhost:3306", "city"); + ActiveRow ar = new ActiveRow(activeDatabase, "101"); + ar.contents = new ArrayList( + Arrays.asList("101", "Godoy Cruz", "ARG", "Mendoza", "206998")); + ar.write(); + System.out.println(ar.read()); + + } catch (Exception e) { + e.printStackTrace(); + } + + } +} diff --git a/active-record/src/main/java/com/iluwatar/activeobject/Rowverride.java b/active-record/src/main/java/com/iluwatar/activeobject/Rowverride.java new file mode 100644 index 000000000000..2088a308e4b5 --- /dev/null +++ b/active-record/src/main/java/com/iluwatar/activeobject/Rowverride.java @@ -0,0 +1,12 @@ +package com.iluwatar.activeobject; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.SOURCE) +public @interface Rowverride { + +} diff --git a/active-record/src/test/java/com/iluwatar/activeobject/ActiveRowTest.java b/active-record/src/test/java/com/iluwatar/activeobject/ActiveRowTest.java new file mode 100644 index 000000000000..4ccc0995dc18 --- /dev/null +++ b/active-record/src/test/java/com/iluwatar/activeobject/ActiveRowTest.java @@ -0,0 +1,56 @@ +package com.iluwatar.activeobject; + +import java.util.ArrayList; +import java.util.Arrays; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + + +public class ActiveRowTest { + + @Test + void initialiseTest() { + ActiveDatabase activeDatabase = new ActiveDatabase("world", "root", "apple-trunks", "localhost:3306", "city"); + ActiveRow row = new ActiveRow(activeDatabase, "1"); + assertDoesNotThrow(row::initialise); + } + + + @Test + void readRowTest() { + ActiveDatabase activeDatabase = new ActiveDatabase("world", "root", "apple-trunks", "localhost:3306", "city"); + ActiveRow row = new ActiveRow(activeDatabase, "1"); + System.out.println(row.read().size()); + int rowSize = row.read().size(); + if (!(row.read().equals(new ArrayList()))) { + for (int i = 0; i < rowSize; i++) { + assertNotNull(row.read().get(i)); + } + } + + } + + @Test + void deleteRowTest() { + ActiveDatabase activeDatabase = new ActiveDatabase("world", "root", "apple-trunks", "localhost:3306", "city"); + ActiveRow row = new ActiveRow(activeDatabase, "1"); + row.delete(); + assertEquals(row.read(), new ArrayList()); + + } + + @Test + void insertRowTest() { + ActiveDatabase activeDatabase = new ActiveDatabase("world", "root", "apple-trunks", "localhost:3306", "city"); + ActiveRow row = new ActiveRow(activeDatabase, "1"); + row.delete(); + row.contents = new ArrayList( + Arrays.asList("101", "Godoy Cruz", "ARG", "Mendoza", "206998")); + assertEquals(row.read(), Arrays.asList("101", "Godoy Cruz", "ARG", "Mendoza", "206998")); + + } + +} diff --git a/active-record/src/test/java/com/iluwatar/activeobject/AppTest.java b/active-record/src/test/java/com/iluwatar/activeobject/AppTest.java new file mode 100644 index 000000000000..61051204d5ec --- /dev/null +++ b/active-record/src/test/java/com/iluwatar/activeobject/AppTest.java @@ -0,0 +1,13 @@ +package com.iluwatar.activeobject; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +class AppTest { + + @Test + void runWithoutException() { + assertDoesNotThrow(() -> App.main(new String[]{})); + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 3aacbad55d4a..f1cefed39d24 100644 --- a/pom.xml +++ b/pom.xml @@ -231,6 +231,7 @@ composite-view metadata-mapping service-to-worker + active-record