Repository: mucsci-students/2025sp-420-CrowdStrike
Pull request #80: Added fields and methods
Author: login: dpbrooks
Created: 2025-03-01T19:19:22Z | Merged: 2025-03-02T15:14:03Z

1. Added fields/methods and their functionality
2. Added parameters class
3. Updated list classes to list fields and methods instead of attributes
4. Switched nested if statements in controller to guard statements
5. Updated ClassObject to store and fetch fields and methods


Diff:
diff --git a/app/src/main/java/org/Controller/CLController.java b/app/src/main/java/org/Controller/CLController.java
index d7b3840..ab8191c 100644
--- a/app/src/main/java/org/Controller/CLController.java
+++ b/app/src/main/java/org/Controller/CLController.java
@@ -4,6 +4,11 @@
 import org.Model.ClassObject;
 import org.View.CLView;
 import org.FileManager;
+import org.Model.AttributeInterface;
+import org.Model.Field;
+import org.Model.Method;
+import org.Model.Parameter;
+import java.util.ArrayList;
 
 // Checks validity of action then calls function in
 // editor to carry out change
@@ -19,6 +24,8 @@ public class CLController {
     private Scanner sc;
     // Create a string to read user input
     private String input = "";
+	// Create a global class that can be used and passed into editor
+	ClassObject activeClass = null;
 	// Prompt to be displayed at beginning of every loop
 	private final String basePrompt = "Please type your command(Help for list of commands): ";
 	
@@ -51,18 +58,24 @@ private void CL_listClasses() {
 	 * Gets the class to be listed and tells user if action failed
 	 */
 	private void CL_listClassInfo() {
-		if (listClassNames()) {
-			view.show("What class would you like printed?");
-			input = sc.nextLine();
-			String classInfo = model.listClassInfo(input);
-			if (classInfo.equals("")) {
-				// Class does not exist
-				view.show("Requested class does not exist");
-			} else {
-				view.show(classInfo);
-			}
-		} else {
+		if (!listClassNames()) {
 			view.show("No classes currently exist");
+			return;
+		}
+		view.show("What class would you like printed?");
+		input = sc.nextLine();
+		activeClass = model.fetchClass(input);
+		if (activeClass == null) {
+			// Class does not exist
+			view.show("Class " + input + " does not exist");
+			return;
+		}
+		String classInfo = model.listClassInfo(activeClass);
+		if (classInfo.equals("")) {
+			// Class does not exist
+			view.show("Requested class does not exist");
+		} else {
+			view.show(classInfo);
 		}
 	}
 	
@@ -109,16 +122,16 @@ private void CL_addClass() {
 	 * Gets class info from user and displays if class was deleted
 	 */
 	private void CL_deleteClass() {
-		if (listClassNames()) {
-			view.show("What class would you like to delete?");
-			input = sc.nextLine();
-			if (editor.deleteClass(input)) {
-				view.show("Class " + input + " successfully deleted");
-			} else {
-				view.show("Class " + input + " could not be deleted");
-			}
-		} else {
+		if (!listClassNames()) {
 			view.show("No classes currently exist");
+			return;
+		}
+		view.show("What class would you like to delete?");
+		input = sc.nextLine();
+		if (editor.deleteClass(input)) {
+			view.show("Class " + input + " successfully deleted");
+		} else {
+			view.show("Class " + input + " could not be deleted");
 		}
 	}
 	
@@ -126,48 +139,51 @@ private void CL_deleteClass() {
 	 * Gets class info from user and displays if class was renamed
 	 */
 	private void CL_renameClass() {
-		if (listClassNames()) {
-			view.show("What class would you like to rename?");
-			input = sc.nextLine();
-			ClassObject activeClass = model.fetchClass(input);
-			if (activeClass != null) {
-				// Class to be renamed exists
-				view.show("What would you like the new name of the class tobe ?");
-				String newName = sc.nextLine();
-				int result = model.isValidClassName(newName);
-				switch(result) {
-				case 1:
-					view.show("No new class name was given");
-					break;
-				case 2:
-					view.show("Name " + newName + " is invalid. First character must be a letter or '_'");
-					break;
-				case 3:
-					view.show("Name " + newName + " is invalid. Name can only contain alphanumerics, '_', or '$'");
-					break;
-				case 4:
-					view.show("Name " + newName + " is alreadyused by another class");
-					break;
-				case 0:
-				default:
-					editor.renameClass(activeClass, newName);
-					view.show("Class " + input + " renmaed to " + newName);
-					break;
-				}
-			} else {
-				// Class to be renamed does not exist
-				view.show("Class " + input + " does not exist");
+		if (!listClassNames()) {
+			view.show("No classes currently exist");
+			return;
+		}
+		view.show("What class would you like to rename?");
+		input = sc.nextLine();
+		activeClass = model.fetchClass(input);
+		if (activeClass != null) {
+			// Class to be renamed exists
+			view.show("What would you like the new name to be?");
+			String newName = sc.nextLine();
+			int result = model.isValidClassName(newName);
+			switch (result) {
+			case 1:
+				view.show("No new class name was given");
+				break;
+			case 2:
+				view.show("Name " + newName + " is invalid. First character must be a letter or '_'");
+				break;
+			case 3:
+				view.show("Name " + newName + " is invalid. Name can only contain alphanumerics, '_', or '$'");
+				break;
+			case 4:
+				view.show("Name " + newName + " is already used by another class");
+				break;
+			case 0:
+			default:
+				editor.renameClass(activeClass, newName);
+				view.show("Class " + input + " renamed to " + newName);
+				break;
 			}
 		} else {
-			view.show("No classes currently exist");
+			// Class to be renamed does not exist
+			view.show("Class " + input + " does not exist");
 		}
-		
 	}
 	
 	/**
 	 * Gets relationship info from user and returns if action succeeded or failed
 	 */
 	private void CL_addRelationship() {
+		if ((model.listClassNames().equals(""))) {
+			view.show("No classes currently exist");
+			return;
+		}
 		view.show("Would you like to give the relationship a name?(Y for yes)");
 		input = sc.nextLine();
 		if (input.equalsIgnoreCase("Y")) {
@@ -176,7 +192,7 @@ private void CL_addRelationship() {
 		} else {
 			input = "";
 		}
-		if (listClassNames()) {
+		listClassNames();
 			view.show("Enter the source class");
 			String source = sc.nextLine();
 			view.show("Enter the destination class");
@@ -186,103 +202,296 @@ private void CL_addRelationship() {
 			} else {
 				view.show("Relationship " + input + " could not be created");
 			}
-		} else {
-			view.show("No classes currently exist");
-		}
-		
 	}
 	
 	/**
 	 * Gets relationship info from user and returns if it was deleted
 	 */
 	private void CL_deleteRelationship() {
-		if (listClassNames()) {
-			view.show("What is the source of the relationship?");
-			input = sc.nextLine();
-			view.show("What is the destination of the relationship?");
-			String dest = sc.nextLine();
-			if (editor.deleteRelationship(input, dest)) {
-				view.show("Relaionship between " + input + " and " + dest + " deleted");
-			} else {
-				view.show("Relaionship between " + input + " and " + dest + " could not be deleted");
-			}
+		if (!listClassNames()) {
+			view.show("No classes currently exist");
+			return;
+		}
+		view.show("What is the source of the relationship?");
+		input = sc.nextLine();
+		view.show("What is the destination of the relationship?");
+		String dest = sc.nextLine();
+		if (editor.deleteRelationship(input, dest)) {
+			view.show("Relaionship between " + input + " and " + dest + " deleted");
 		} else {
+			view.show("Relaionship between " + input + " and " + dest + " could not be deleted");
+		}
+	}
+
+	/**
+	 * Gets class and field info from user and returns if action succeeded or not
+	 */
+	private void CL_addField() {
+		if (!listClassNames()) {
 			view.show("No classes currently exist");
+			return;
+		}
+		view.show("What class would you like to add a field to?");
+		String className = sc.nextLine();
+		activeClass = model.fetchClass(className);
+		if (activeClass == null) {
+			// Class does not exist
+			view.show("Class " + className + " does not exist");
+			return;
+		}
+		view.show("What do you want to name the field?");
+		input = sc.nextLine();
+		if (activeClass.fetchField(input) == null) {
+			// Field does not already exist in class
+			editor.addField(activeClass, input);
+			view.show("Field " + input + " successfully added to class " + className);
+		} else {
+			view.show("Field with name " + input + " already exists in class " + className);
 		}
-		
 	}
-	
+
 	/**
-	 * Gets class and attribute info from user and returns if action succeeded or not
+	 * Gets class and field info from user and returns if deletion succeeded
 	 */
-	private void CL_addAttribute() {
-		if (listClassNames()) {
-			view.show("What class would you like to add an attribute to?");
-			String className = sc.nextLine();
-			view.show("What do you want to name the attribute?");
-			input = sc.nextLine();
-			if (editor.addAttribute(className, input)) {
-				// editor.addAttribute succeeded
-				view.show("Attribute " + input + " was successfully added to class " + className);
+	private void CL_deleteField() {
+		if (!listClassNames()) {
+			view.show("No classes currently exist");
+			return;
+		}
+		view.show("What class would you like to delete a field from?");
+		String className = sc.nextLine();
+		activeClass = model.fetchClass(className);
+		if (activeClass == null) {
+			// Class does not exist
+			view.show("Class " + className + " does not exist");
+			return;
+		}
+		if (!listFieldNames(activeClass)) {
+			view.show("Class has no fields");
+			return;
+		}
+		view.show("What is the name of the field you want to delete?");
+		input = sc.nextLine();
+		AttributeInterface delField = activeClass.fetchField(input);
+		if (delField != null) {
+			// The field specified exists
+			editor.deleteAttribute(activeClass, delField);
+			view.show("Field " + input + " successfully deleted from class " + className);
+		} else {
+			// The field does not exist
+			view.show("Class " + className + " does not have a field named " + input);
+		}
+	}
+
+	/**
+	 * Gets class and field info from user as well as what they want to rename it to
+	 * Returns whether or not the operation succeeds
+	 */
+	private void CL_renameField() {
+		if (!listClassNames()) {
+			view.show("No classes currently exist");
+			return;
+		}
+		view.show("What class do you want to rename a field from?");
+		String className = sc.nextLine();
+		activeClass = model.fetchClass(className);
+		if (activeClass == null) {
+			// Class does not exist
+			view.show("Class " + className + " does not exist");
+			return;
+		}
+		if (!listFieldNames(activeClass)) {
+			view.show("Class has no fields");
+			return;
+		}
+		view.show("What is the name of the field you want to rename?");
+		input = sc.nextLine();
+		AttributeInterface renameField = activeClass.fetchField(input);
+		if (renameField != null) {
+			// The method does exist
+			view.show("What do you want to rename the field to?");
+			String newName = sc.nextLine();
+			if (activeClass.fetchField(newName) == null) {
+				// The newName is not in use
+				editor.renameAttribute(renameField, newName);
+				view.show("Field " + input + " renamed to " + newName);
 			} else {
-				view.show("Attribute " + input + " could not be created");
+				view.show(newName + " is currently used by another field in " + className);
 			}
 		} else {
-			view.show("No classes currently exist");
+			// The method does not exist
+			view.show("Class " + className + " does not have a field named " + input);
 		}
-		
 	}
-	
+
 	/**
-	 * Gets class and attribute info from user and returns if deletion succeeded
+	 * Gets class, method, and parameters from user and returns if action succeeded
+	 * or not
 	 */
-	private void CL_deleteAttribute() {
-		if (listClassNames()) {
-			view.show("What class would you like to delete an attribute from?");
-			input = sc.nextLine();
-			if (listAttrNames(input)) {
-				view.show("What is the name of the attribute you want to delete?");
-				String attrName = sc.nextLine();
-				if (editor.deleteAttribute(input, attrName)) {
-					view.show("Attribute " + attrName + " deleted from " + input);
+	private void CL_addMethod() {
+		if (!listClassNames()) {
+			view.show("No classes currently exist");
+			return;
+		}
+		view.show("What class would you like to add a method to?");
+		String className = sc.nextLine();
+		activeClass = model.fetchClass(className);
+		if (activeClass == null) {
+			// Class does not exist
+			view.show("Class " + className + " does not exist");
+			return;
+		}
+		// Class exists, get Method name and params
+		view.show("What do you want to name the method?");
+		input = sc.nextLine();
+		ArrayList<Parameter> paramList = new ArrayList<>();
+		view.show("Would you like to add parameters to this method? (Y for yes)");
+		if (sc.nextLine().replaceAll("\\s", "").equalsIgnoreCase("Y")) {
+			boolean loop = true;
+			String paramName = "";
+			Parameter param;
+			view.show("What would you like to name the parameter? Type 'stop' to stop adding parameters");
+			while (loop) {
+				view.show("What would you like to name the next parameter?");
+				paramName = sc.nextLine().replaceAll("\\s", "");
+				if (paramName.equalsIgnoreCase("stop")) {
+					loop = false;
 				} else {
-					view.show("Attribute could not be deleted");
+					boolean exist = false;
+					for (int i = 0; i < paramList.size(); i++) {
+						if (paramName.equals(paramList.get(i).getName())) {
+							// Parameter name has already been added
+							exist = true;
+							break;
+						} else {
+							// Do nothing
+						}
+					}
+					if (exist) {
+						view.show("Parameter " + paramName + " has already been added");
+					} else {
+						param = new Parameter(paramName);
+						paramList.add(param);
+						view.show("Parameter " + paramName + " added to method " + input);
+					}
 				}
-			} else {
-				view.show("Class has no attributes");
 			}
-			
+		}
+		if (activeClass.fetchMethod(input, paramList.size()) != null) {
+			// Method with same name and # of parameters already exists
+			view.show("Method with name " + input + " and parameter arity " + paramList.size() + " already exists");
 		} else {
+			// Method with same name and # of parameters does not exist
+			editor.addMethod(activeClass, input, paramList);
+			view.show("Method " + input + " successfully added to class " + className);
+		}
+	}
+
+	/**
+	 * Gets class and method info from user and returns if deletion succeeded
+	 */
+	private void CL_deleteMethod() {
+		if (!listClassNames()) {
 			view.show("No classes currently exist");
+			return;
+		}
+		view.show("What class would you like to delete a method from?");
+		String className = sc.nextLine();
+		activeClass = model.fetchClass(className);
+		if (activeClass == null) {
+			// Class does not exist
+			view.show("Class " + className + " does not exist");
+			return;
+		}
+		if (!listMethodNames(activeClass)) {
+			view.show("Class has no methods");
+			return;
+		}
+		view.show("What is the name of the method you want to delete?");
+		input = sc.nextLine();
+		int paramArity = -1;
+		view.show("How many parameters does " + input + " have?");
+		if (sc.hasNextInt()) {
+			paramArity = sc.nextInt();
+			if (paramArity < 0) {
+				view.show("Parameter arity must be non-negative");
+				return;
+			}
+			// Consume newLine char left by nextInt
+			sc.nextLine();
+		} else {
+			view.show("Invalud input. Please enter a number");
+			// Clear invalid input from buffer
+			sc.nextLine();
+			return;
+		}
+		Method delMethod = activeClass.fetchMethod(input, paramArity);
+		if (delMethod != null) {
+			// The method specified exists
+			editor.deleteAttribute(activeClass, delMethod);
+			view.show("Method " + input + " successfully deleted from class " + className);
+		} else {
+			// The method does not exist
+			view.show("Class " + className + " does not have a method named " + input);
 		}
-		
 	}
-	
+
 	/**
-	 * Gets class and attribute info and new name from user and returns if
-	 * operation succeeded
+	 * Gets class and method info from user as well as what they want to rename it
+	 * to Returns whether or not the operation succeeds
 	 */
-	private void CL_renameAttribute() {
-		if (listClassNames()) {
-			view.show("What class do you want to rename an attribute from?");
-			input = sc.nextLine();
-			if (listAttrNames(input)) {
-				view.show("What attribute do you want to rename?");
-				String attrName = sc.nextLine();
-				view.show("What do you want to rename the attribute to?");
-				String newName = sc.nextLine();
-				if (editor.renameAttribute(input, attrName, newName)) {
-					view.show("Attribute " + attrName + " renamed to " + newName);
-				} else {
-					view.show("Attribute " + attrName + " could not be renamed");
-				}
+	private void CL_renameMethod() {
+		if (!listClassNames()) {
+			view.show("No classes currently exist");
+			return;
+		}
+		view.show("What class do you want to rename a method from?");
+		String className = sc.nextLine();
+		activeClass = model.fetchClass(className);
+		if (activeClass == null) {
+			// Class does not exist
+			view.show("Class " + className + " does not exist");
+			return;
+		}
+		if (!listMethodNames(activeClass)) {
+			view.show("Class has no methods");
+			return;
+		}
+		view.show("What is the name of the method you want to rename?");
+		input = sc.nextLine();
+		int paramArity = -1;
+		view.show("How many parameters does " + input + " have?");
+		if (sc.hasNextInt()) {
+			paramArity = sc.nextInt();
+			if (paramArity < 0) {
+				view.show("Parameter arity must be non-negative");
+				return;
+			}
+			// Consume newLine char left by nextInt
+			sc.nextLine();
+		} else {
+			view.show("Invalud input. Please enter a number");
+			// Clear invalid input from buffer
+			sc.nextLine();
+			return;
+		}
+		Method renameMethod = activeClass.fetchMethod(input, paramArity);
+		if (renameMethod != null) {
+			// The method does exist
+			view.show("What do you want to rename the method to?");
+			String newName = sc.nextLine();
+			if (activeClass.fetchMethod(newName, paramArity) == null) {
+				// The newName is not in use
+				editor.renameAttribute(renameMethod, newName);
+				view.show("Method " + input + " renamed to " + newName);
 			} else {
-				view.show("Class has no attributes");
+				view.show(newName + " is currently used by another method in " + className);
 			}
 		} else {
-			view.show("No classes currently exist");
+			// The method does not exist
+			view.show("Class " + className + " does not have a method named " + input + " with " + paramArity
+					+ " parameters");
 		}
-		
 	}
 	
 	/**
@@ -300,15 +509,30 @@ private boolean listClassNames() {
 	}
 	
 	/**
-	 * Helper class to return if any attributes have been listed
-	 * Used for error catching and avoiding redundant code
-	 * @param className		| Name of the class being checked
-	 * @return True if attributes have been listed, false otherwise
+	 * Helper function to return if any fields have been listed
+	 * 
+	 * @param cls | The class whose fields are being listed
+	 * @return True if fields have been listed, false otherwise
+	 */
+	private boolean listFieldNames(ClassObject cls) {
+		String fieldNames = model.listFields(cls);
+		if (!fieldNames.equals("")) {
+			view.show("Available Fields:\n" + fieldNames);
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Helper function to return if any methods have been listed
+	 * 
+	 * @param cls | The class whose methods are being listed
+	 * @return True if methods have been listed, false otherwise
 	 */
-	private boolean listAttrNames(String className) {
-		String attrNames = model.listAttributes(className);
-		if (!attrNames.equals("")) {
-			view.show("Available Attributes:\n" + attrNames);
+	private boolean listMethodNames(ClassObject cls) {
+		String methodNames = model.listMethods(cls);
+		if (!methodNames.equals("")) {
+			view.show("Available Methods:\n" + methodNames);
 			return true;
 		}
 		return false;
@@ -349,13 +573,12 @@ public void init() {
         	// Print the basePrompt asking for next command
         	view.show(basePrompt);
         	// Read user input
-		if(!sc.hasNextLine())
-		    continue;
+			if(!sc.hasNextLine())
+		    	continue;
         	input = sc.nextLine();
         	
         	switch(input.toLowerCase().replaceAll("\\s", "")) {
         	case "help":
-        		//TODO
 				view.showHelp();
         		break;
         	case "save":
@@ -377,43 +600,45 @@ public void init() {
         		CL_listRelationships();
         		break;
         	case "addclass":
-        		//TODO
         		CL_addClass();
         		break;
         	case "deleteclass":
-        		//TODO
         		CL_deleteClass();
         		break;
         	case "renameclass":
-        		//TODO
         		CL_renameClass();
         		break;
         	case "addrelationship":
-        		//TODO
         		CL_addRelationship();
         		break;
         	case "deleterelationship":
-        		//TODO
         		CL_deleteRelationship();
         		break;
-        	case "addattribute":
-        		//TODO
-        		CL_addAttribute();
+        	case "addfield":
+        		CL_addField();
         		break;
-        	case "deleteattribute":
-        		//TODO
-        		CL_deleteAttribute();
+        	case "deletefield":
+        		CL_deleteField();
         		break;
-        	case "renameattribute":
-        		//TODO
-        		CL_renameAttribute();
+        	case "renamefield":
+        		CL_renameField();
         		break;
+			case "addmethod":
+				CL_addMethod();
+				break;
+			case "deletemethod":
+				CL_deleteMethod();
+				break;
+			case "renamemethod":
+				CL_renameMethod();
+				break;
         	default:
         		view.show("Command not recognized, please try something else");
         		break;
         	}
         	// Reset Variables
         	input = "";
+			activeClass = null;
         	// Skip a line to break up user actions in the command line
         	view.show("");
         }
diff --git a/app/src/main/java/org/Controller/UMLEditor.java b/app/src/main/java/org/Controller/UMLEditor.java
index a42dde3..98b3cf6 100644
--- a/app/src/main/java/org/Controller/UMLEditor.java
+++ b/app/src/main/java/org/Controller/UMLEditor.java
@@ -2,7 +2,11 @@
 import org.Model.UMLModel;
 import org.Model.ClassObject;
 import org.Model.Relationship;
-import org.Model.Attribute;
+import org.Model.AttributeInterface;
+import org.Model.Field;
+import org.Model.Method;
+import org.Model.Parameter;
+import java.util.ArrayList;
 
 public class UMLEditor {
 	// The model that is being edited
@@ -144,75 +148,45 @@ public boolean deleteRelationship(String source, String dest) {
 	}
 
 	/**
-	 * Adds attribute to the indicated class
+	 * Adds a field to the designated ClassObject
 	 * 
-	 * @param className | Name of class to add attribute to
-	 * @param newAttr   | Attribute to be added
-	 * @return True if operation succeeded, false otherwise
+	 * @param cls			| The class the method is being added to
+	 * @param fieldName		| The name of the field
 	 */
-	public boolean addAttribute(String className, String attrName) {
-		// Use the class name to fetch the ClassObject from classList
-		activeClass = model.fetchClass(className);
-		if (activeClass != null) {
-			// Class exists
-			if (activeClass.fetchAttribute(attrName) == null) {
-				// Attribute does not exist
-				Attribute newAttr = new Attribute(attrName);
-				activeClass.addAttribute(newAttr);
-				resetActiveClass();
-				return true;
-			}
-		}
-		resetActiveClass();
-		return false;
+	public void addField(ClassObject cls, String fieldName) {
+		Field fld = new Field(fieldName);
+		cls.addAttribute(fld);
 	}
-
+	
 	/**
-	 * Deletes attribute from the indicated class
+	 * Adds a method to the designated ClassObject
 	 * 
-	 * @param className | Name of class to delete attribute from
-	 * @param delAttr   | Attribute to be removed
-	 * @return True if operation succeeded, false otherwise
+	 * @param cls			| The class the method is being added to
+	 * @param methodName	| The name of the method
+	 * @param paramList		| The parameter list the method will have
 	 */
-	public boolean deleteAttribute(String className, String attrName) {
-		// Use the class name to fetch the ClassObject from classList
-		activeClass = model.fetchClass(className);
-		if (activeClass != null) {
-			// Class exists
-			Attribute attr = activeClass.fetchAttribute(attrName);
-			if (attr != null) {
-				// Attribute exists in class
-				activeClass.removeAttribute(attr);
-				resetActiveClass();
-				return true;
-			}
-		}
-		resetActiveClass();
-		return false;
+	public void addMethod(ClassObject cls, String methodName, ArrayList<Parameter> paramList) {
+		Method method = new Method(methodName, paramList);
+		cls.addAttribute(method);
 	}
 
 	/**
-	 * Renames the indicated attribute in the indicated class
+	 * Deletes fields or methods from the designated ClassObject
 	 * 
-	 * @param className | Name of class attribute is in
-	 * @param curName   | Current name of the attribute to be renamed
-	 * @param newName   | New name to give attribute
-	 * @return True if operation succeeded, false otherwise
+	 * @param cls 		| The class from which the field/method is to be deleted from
+	 * @param delAttr   | The field/method to be removed
 	 */
-	public boolean renameAttribute(String className, String curName, String newName) {
-		// Use the class name to fetch the ClassObject from classList
-		activeClass = model.fetchClass(className);
-		if (activeClass != null) {
-			// Class exists
-			Attribute attr = activeClass.fetchAttribute(curName);
-			if (attr != null) {
-				// Attribute exists
-				attr.renameAttribute(newName);
-				resetActiveClass();
-				return true;
-			}
-		}
-		resetActiveClass();
-		return false;
+	public void deleteAttribute(ClassObject cls, AttributeInterface delAttr) {
+		cls.removeAttribute(delAttr);
+	}
+	
+	/**
+	 * Renames fields or methods from the designated ClassObject
+	 * 
+	 * @param renameAttr	| The filed/method being renamed
+	 * @param newName		| The new name for the field/method
+	 */
+	public void renameAttribute(AttributeInterface renameAttr, String newName) {
+		renameAttr.renameAttribute(newName);
 	}
 }
diff --git a/app/src/main/java/org/Model/Attribute.java b/app/src/main/java/org/Model/Attribute.java
deleted file mode 100644
index 8c1ffaf..0000000
--- a/app/src/main/java/org/Model/Attribute.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.Model;
-public class Attribute implements AttributeInterface {
-
-	// Attribute Name
-	private String name;
-	
-	/**
-	 * Constructor to create a new attribute
-	 * @param name	| the name of the attribute
-	 */
-	public Attribute(String name) {
-		this.name = name;
-	}
-	
-	@Override
-	public String getName() {
-		// TODO Auto-generated method stub
-		return name;
-	}
-
-	@Override
-	public void renameAttribute(String newName) {
-		// TODO Auto-generated method stub
-		this.name = newName;
-	}
-}
diff --git a/app/src/main/java/org/Model/AttributeInterface.java b/app/src/main/java/org/Model/AttributeInterface.java
index 581cf70..76ba8e1 100644
--- a/app/src/main/java/org/Model/AttributeInterface.java
+++ b/app/src/main/java/org/Model/AttributeInterface.java
@@ -6,6 +6,12 @@ public interface AttributeInterface {
 	 * @return String name
 	 */
 	public String getName();
+
+	/**
+	 * Returns the attribute's type
+	 * @return "Field" if the attribute is a field "Method" if it's a method
+	 */
+	public String getType();
 	
 	/**
 	 * Changes an attribute's name
diff --git a/app/src/main/java/org/Model/ClassObject.java b/app/src/main/java/org/Model/ClassObject.java
index 7368722..6af46b4 100644
--- a/app/src/main/java/org/Model/ClassObject.java
+++ b/app/src/main/java/org/Model/ClassObject.java
@@ -1,14 +1,15 @@
 package org.Model;
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 
 //Creates a Class object
 public class ClassObject implements ClassObjectInterface {
 
-	//Name of a class
+	// Name of a class
 	private String name;
 
-	//Stores all attributes belonging to a class
-	private ArrayList<Attribute> attrList;
+	// Stores all attributes belonging to a class
+	private LinkedHashMap<String, ArrayList<AttributeInterface>> attrMap;
 	
 	/**
 	 * Constructs a class object
@@ -16,7 +17,14 @@ public class ClassObject implements ClassObjectInterface {
 	 */
 	public ClassObject(String name) {
 		this.name = name;
-		attrList = new ArrayList<>();
+		attrMap = new LinkedHashMap<>();
+		// Need to create the Maps to be paired with each key
+		ArrayList<AttributeInterface> fieldList = new ArrayList<>();
+		ArrayList<AttributeInterface> methodList = new ArrayList<>();
+		// Add Maps to the map paired with keys based on the type
+		// Should probably add functions in ClassObject to get these lists
+		attrMap.put("Field", fieldList);
+		attrMap.put("Method", methodList);
 	}
 	
 	/**
@@ -30,32 +38,70 @@ public String getName() {
 	public void setName(String newName) {
 		this.name = newName;
 	}
+
+	/**
+	 * Gets the HashMap containing lists of fields and methods
+	 * @return HashMap containing ArrayLists of fields and methods
+	 */
+	public LinkedHashMap<String, ArrayList<AttributeInterface>> getAttrMap() {
+		return attrMap;
+	}
 	
 	/**
-	 * Gets the attribute list that correlates to this class object
+	 * Gets the ArrayList containing fields
+	 * @return ArrayList containing fields
 	 */
-	public ArrayList<Attribute> getAttrList() {
-		return attrList;
+	public ArrayList<AttributeInterface> getFieldList() {
+		return attrMap.get("Field");
+	}
+	
+	/**
+	 * Gets the ArrayList containing methods
+	 * @return ArrayList containing methods
+	 */
+	public ArrayList<AttributeInterface> getMethodList() {
+		return attrMap.get("Method");
 	}
 	
 	@Override
-	public void addAttribute(Attribute attr) {
-		attrList.add(attr);
+	public void addAttribute(AttributeInterface attr) {
+		attrMap.get(attr.getType()).add(attr);
 	}
+	
 	@Override
-	public void removeAttribute(Attribute attr) {
-		attrList.remove(attr);
+	public void removeAttribute(AttributeInterface attr) {
+		attrMap.get(attr.getType()).remove(attr);
 	}
 	
 	@Override
-	public Attribute fetchAttribute(String attrName) {
+	public Field fetchField(String fieldName) {
 		int index = 0;
-        	// Iterate through the array of classes
-        while (index < attrList.size()) {
+        // Iterate through the array of classes
+        while (index < attrMap.get("Field").size()) {
             // Check if the current class' name equals the given className
-            if (attrName.equals(attrList.get(index).getName())) {
+            if (fieldName.equals(attrMap.get("Field").get(index).getName())) {
                 // If yes, then it exists and return true
-                return attrList.get(index);
+                return (Field) attrMap.get("Field").get(index);
+            }
+            index++;
+        }
+        // Class with className did not exist, return false
+        return null;
+	}
+	
+	@Override
+	public Method fetchMethod(String methodName, int paramArity) {
+		int index = 0;
+        // Iterate through the array of classes
+        while (index < attrMap.get("Method").size()) {
+            // Check if the current method's name equals the given methodName
+            if (methodName.equals(attrMap.get("Method").get(index).getName())) {
+            	// If yes, check if paramArity == # of param's current method has
+            	// Need to cast as a method to access paramList
+                Method activeMethod = (Method) attrMap.get("Method").get(index);
+                if (activeMethod.getParamList().size() == paramArity) {
+                	return activeMethod;
+                }
             }
             index++;
         }
diff --git a/app/src/main/java/org/Model/ClassObjectInterface.java b/app/src/main/java/org/Model/ClassObjectInterface.java
index 1e3fa26..05b8491 100644
--- a/app/src/main/java/org/Model/ClassObjectInterface.java
+++ b/app/src/main/java/org/Model/ClassObjectInterface.java
@@ -10,17 +10,24 @@ public interface ClassObjectInterface {
 	 * Adds an attribute to the attribute list that is assigned to this class object
 	 * @param attr		| The new attribute that will be added to the attribute list
 	 */
-	public void addAttribute(Attribute attr);
+	public void addAttribute(AttributeInterface attr);
 
 	/**
 	 * Removes a specific attribute from the list of attributes
 	 * @param attr		| The attribute that will be removed from the attribute list 
 	 */
-	public void removeAttribute(Attribute attr);
+	public void removeAttribute(AttributeInterface attr);
 
 	/**
-	 * Fetches the specific attribute from the list of attribute
+	 * Fetches the specific field from the list of fields
 	 * @param attrName		| The given name that will be searched for
 	 */
-	public Attribute fetchAttribute(String attrName);
+	public Field fetchField(String fieldName);
+
+	/**
+	 * Fetches the specific method from the list of methods
+	 * @param attrName		| The given name that will be searched for
+	 * @param paramArity	| The number of params the method should have
+	 */
+	public Method fetchMethod(String methodName, int paramArity);
 }
diff --git a/app/src/main/java/org/Model/Field.java b/app/src/main/java/org/Model/Field.java
new file mode 100644
index 0000000..37ebc70
--- /dev/null
+++ b/app/src/main/java/org/Model/Field.java
@@ -0,0 +1,31 @@
+package org.Model;
+public class Field implements AttributeInterface {
+
+	// Date Fields
+	private String name;
+	private String type;
+	
+	/**
+	 * Constructor to create a new field
+	 * @param name	| the name of the field
+	 */
+	public Field(String name) {
+		this.name = name;
+		type = "Field";
+	}
+	
+	@Override
+	public String getName() {
+		return name;
+	}
+
+	@Override
+	public String getType() {
+		return type;
+	}
+
+	@Override
+	public void renameAttribute(String newName) {
+		this.name = newName;
+	}
+}
diff --git a/app/src/main/java/org/Model/Method.java b/app/src/main/java/org/Model/Method.java
new file mode 100644
index 0000000..00f808d
--- /dev/null
+++ b/app/src/main/java/org/Model/Method.java
@@ -0,0 +1,102 @@
+package org.Model;
+
+import java.util.ArrayList;
+
+public class Method implements AttributeInterface {
+
+	// Data Fields
+	private String name;
+	private String type;
+	private ArrayList<Parameter> paramList;
+	
+    /**
+	 * Constructor to create a new method
+	 * @param name			| The name of the method
+	 * @param paramList		| List of parameters the method contains
+	 */
+	public Method(String name, ArrayList<Parameter> paramList) {
+		this.name = name;
+		type = "Method";
+		this.paramList = paramList;
+	}
+	
+	@Override
+	public String getName() {
+		return name;
+	}
+	
+    @Override
+	public String getType() {
+		return type;
+	}
+	
+    /**
+	 * Returns the paramList of the method
+	 * @return The method's parameter list
+	 */
+	public ArrayList<Parameter> getParamList() {
+		return paramList;
+	}
+
+	@Override
+	public void renameAttribute(String newName) {
+		name = newName;
+	}
+	
+	/**
+	 * Concatenates the parameter list moreParams to the end of
+	 * paramList
+	 * @param moreParams	| List of params being added
+	 */
+	public void addParameter(ArrayList<Parameter> moreParams) {
+		paramList.addAll(moreParams);
+	}
+	
+    /**
+	 * Removes all elements of paramList
+	 */
+	public void removeAllParameters() {
+		paramList.clear();
+	}
+	
+    /**
+	 * Removes the designated parameter from paramList
+	 * @param param		| The parameter to be removed
+	 */
+	public void removeParameter(Parameter param) {
+		paramList.remove(param);
+	}
+	
+    /**
+	 * Checks if this method is equal to the one being passed in
+	 * @param compareMethod		| The method this is being compared to
+	 * @return True if this is equal to compareMethod, false otherwise
+	 */
+	public boolean equals(Method compareMethod) {
+		if (this.name == compareMethod.getName() && this.paramList.size() == compareMethod.getParamList().size()) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 * Fetches the specific parameter from the list of params
+	 * @param paramName		| The given name that will be searched for
+	 */
+	public Parameter fetchParameter(String paramName) {
+		int index = 0;
+        // Iterate through the array of params
+        while (index < paramList.size()) {
+            // Check if the current param's name equals the given className
+            if (paramName.equals(paramList.get(index).getName())) {
+                // If yes, then it exists and return true
+                return paramList.get(index);
+            }
+            index++;
+        }
+        // Class with className did not exist, return false
+        return null;
+	}
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/Model/Parameter.java b/app/src/main/java/org/Model/Parameter.java
new file mode 100644
index 0000000..8eab74b
--- /dev/null
+++ b/app/src/main/java/org/Model/Parameter.java
@@ -0,0 +1,18 @@
+package org.Model;
+
+public class Parameter {
+
+	private String name;
+	
+	public Parameter(String name) {
+		this.name = name;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+	public void setName(String newName) {
+		name = newName;
+	}
+}
diff --git a/app/src/main/java/org/Model/UMLModel.java b/app/src/main/java/org/Model/UMLModel.java
index dec852d..56f4b37 100644
--- a/app/src/main/java/org/Model/UMLModel.java
+++ b/app/src/main/java/org/Model/UMLModel.java
@@ -117,67 +117,23 @@ public void updateLongest() {
      * @return String listing all classes and their info
      */
 	public String listClasses() {
-        ClassObject curClass;
-        Relationship curRelationship;
-        int index1 = 0;
-        int index2 = 0;
-        // Strings to keep relationships where curClass is source or dest together
-        String sourceRelationships = "";
-        String destRelationships = "";
-        // String to be returned that contains list of classes and info
-        String finalString = "";
-        while (index1 < classList.size()) {
-            // Save current class in curClass
-            curClass = classList.get(index1);
-            // Add Class name to finalString
-            finalString = finalString + "Class Name: " + curClass.getName() + "\n  Attributes:\n";
-            // Iterate through the attribute list stored in each class
-            while (index2 < curClass.getAttrList().size()) {
-                // Add all attributes in attrList for curClass to finalString
-                finalString = finalString + "   " + curClass.getAttrList().get(index2).getName() + "\n";
-                index2++;
-            }
-            index2 = 0;
-            // Iterate through relationship list to find all relationships involving the current class
-            while (index2 < relationshipList.size()) {
-                curRelationship = relationshipList.get(index2);
-                if (curRelationship.getSource().getName().equals(curClass.getName())) {
-                    // Current class is current relationship's source
-                    // Create a String of the curRelationship and format using relationshipLength
-                	String newSource = curRelationship.getName() + " ".repeat(relationshipLength - curRelationship.getName().length()) + ": " + curRelationship.getSource().getName() + " -> " + curRelationship.getDestination().getName();
-                	// Add formatted String to sourceRelatiosnhips
-                	sourceRelationships = sourceRelationships + "\n    " + newSource;
-                } else if (curRelationship.getDestination().getName().equals(curClass.getName())) {
-                    // Current class is current relationhip's destination
-                    // Create a String of the curRelationship and format using relationshipLength
-                	String newDest =  curRelationship.getName() + " ".repeat(relationshipLength - curRelationship.getName().length()) + ": " + curRelationship.getSource().getName() + " -> " + curRelationship.getDestination().getName();
-                	// Add formatted String to destRelatiosnhips
-                	destRelationships = destRelationships + "\n    " + newDest;
-                } else {
-                    // Current relationship does not involve the class
-                }
-                index2++;
-            }
-            // Add Relationships to finalString
-            finalString = finalString + "  Relationships:" + sourceRelationships + destRelationships + "\n";
-            // Reset values and increment index1
-            sourceRelationships = "";
-            destRelationships = "";
-            index2 = 0;
-            index1++;
-        }
-        return finalString;
-    }
+		String finalString = "";
+		// Iterate through the classList to call printClassInfo on each class to make its String
+		for (int i = 0; i < classList.size(); i++) {
+			finalString = finalString + listClassInfo(classList.get(i));
+		}
+		return finalString;
+	}
 
 	/**
 	 * List the info of a specified class
-	 * @param className		| The name of the class to be printed
+	 * @param cls		| The class to be printed
 	 * @return A String containing the list of specified class' info or 
 	 * 		   empty string if class does not exist
 	 */
-	public String listClassInfo(String className) {
-        ClassObject printClass = fetchClass(className);
-        if (printClass == null) {
+	public String listClassInfo(ClassObject cls) {
+		//ClassObject printClass = fetchClass(className);
+        if (cls == null) {
         	// Class does not exist
         	return "";
         }
@@ -185,27 +141,34 @@ public String listClassInfo(String className) {
         Relationship curRelationship;
         String sourceRelationships = "";
         String destRelationships = "";
-        String finalString = "";
         // Add class name to finalString
-        finalString = "Class Name: " + printClass.getName() + "\n  Attributes:\n";
-        // Iterate through attribute list and print
-        while (index < printClass.getAttrList().size()) {
-            // Add all attributes in attrList for printClass to finalString
-            finalString = finalString + "   " + printClass.getAttrList().get(index).getName() + "\n";
-            index++;
+        String finalString = "Class Name: " + cls.getName() + "\n  Fields:\n";
+        // Add Fields to finalString
+        for (int i = 0; i < cls.getFieldList().size(); i++) {
+        	finalString = finalString + "   " +  cls.getFieldList().get(i).getName() + "\n";
+        }
+        finalString = finalString + "  Methods:\n";
+        for (int i = 0; i < cls.getMethodList().size(); i++) {
+        	Method method1 = (Method) cls.getMethodList().get(i);
+        	finalString = finalString + "   " + method1.getName() + "\n     Parameters:\n"; 
+        	for (int j = 0; j < method1.getParamList().size(); j++) {
+        		finalString = finalString + "       " + method1.getParamList().get(j).getName() + "\n";
+        	}
         }
-        // Reset index
-        index = 0;
+        /*
+         * Call the listRelationships function passing in the class to get that part
+         * of the string
+         */
         while(index < relationshipList.size()) {
             // Set current relationship to curRelationship
             curRelationship = relationshipList.get(index);
-            if (curRelationship.getSource().getName().equals(printClass.getName())) {
+            if (curRelationship.getSource().getName().equals(cls.getName())) {
             	// Current class is current relationship's source
                 // Create a String of the curRelationship and format using relationshipLength
             	String newSource = curRelationship.getName() + " ".repeat(relationshipLength - curRelationship.getName().length()) + ": " + curRelationship.getSource().getName() + " -> " + curRelationship.getDestination().getName();
             	// Add formatted String to sourceRelatiosnhips
             	sourceRelationships = sourceRelationships + "\n    " + newSource;
-            } else if (curRelationship.getDestination().getName().equals(printClass.getName())) {
+            } else if (curRelationship.getDestination().getName().equals(cls.getName())) {
             	// Current class is current relationhip's destination
                 // Create a String of the curRelationship and format using relationshipLength
             	String newDest =  curRelationship.getName() + " ".repeat(relationshipLength - curRelationship.getName().length()) + ": " + curRelationship.getSource().getName() + " -> " + curRelationship.getDestination().getName();
@@ -265,23 +228,54 @@ public String listClassNames() {
     	}
     	return finalString;
     }
+
+     /**
+     * Creates a list of all created fields in the given class
+     * 
+     * @param cls	| Class whose fields are being listed
+     * @return A string of all fields in the class
+     */
+    public String listFields(ClassObject cls) {
+    	ArrayList<AttributeInterface> fieldList = cls.getFieldList();
+    	if (fieldList.size() == 0) {
+    		return "";
+    	}
+    	int countNewLine = 0;
+    	int index = 1;
+    	String finalString = "- " + fieldList.get(0).getName();
+    	AttributeInterface attr;
+    	while (index < fieldList.size()) {
+    		attr = fieldList.get(index);
+    		if (countNewLine >= 5) {
+    			// Create a new line after every six names
+    			finalString = finalString + "\n- " + attr.getName();
+    			countNewLine = 0;
+    		} else {
+    			finalString = finalString + "   - " + attr.getName();
+    			countNewLine++;
+    		}
+    		index++;
+    	}
+    	return finalString;
+    }
     
     /**
-     * Creates a list of all created attributes in a given class
-     * @param className		| Class whose attributes are being listed
-     * @return A String of all attributes in the class
+     * Creates a list of all created methods in the given class
+     * 
+     * @param cls	| Class whose methods are being listed
+     * @return A string containing all methods in the class
      */
-    public String listAttributes(String className) {
-    	ArrayList<Attribute> attrList = fetchClass(className).getAttrList();
-    	if (attrList.size() == 0) {
+    public String listMethods(ClassObject cls) {
+    	ArrayList<AttributeInterface> methodList = cls.getMethodList();
+    	if (methodList.size() == 0) {
     		return "";
     	}
     	int countNewLine = 0;
     	int index = 1;
-    	String finalString = "- " + attrList.get(0).getName();
-    	Attribute attr;
-    	while (index < attrList.size()) {
-    		attr = attrList.get(index);
+    	String finalString = "- " + methodList.get(0).getName();
+    	AttributeInterface attr;
+    	while (index < methodList.size()) {
+    		attr = methodList.get(index);
     		if (countNewLine >= 5) {
     			// Create a new line after every six names
     			finalString = finalString + "\n- " + attr.getName();
diff --git a/app/src/main/java/org/Model/UMLModelInterface.java b/app/src/main/java/org/Model/UMLModelInterface.java
index 1a64764..b0a0ca5 100644
--- a/app/src/main/java/org/Model/UMLModelInterface.java
+++ b/app/src/main/java/org/Model/UMLModelInterface.java
@@ -7,78 +7,87 @@ public interface UMLModelInterface {
      * Returns the classList
      * @return list of created classes
      */
-public ArrayList<ClassObject> getClassList();
-
-/**
-     * Returns the relationshipList
-     * @return list of created relationships
-     */
-public ArrayList<Relationship> getRelationshipList();
-
-/**
-     * Returns the length of the longest relationship name
-     * @return relationshipLength
-     */
-public int getRelationshipLength();
-
-/**
-     * Updates relationshipLength
-     * @param newLen Length of new longest relationship name
+    public ArrayList<ClassObject> getClassList();
+	
+    /**
+    * Returns the relationshipList
+    * @return list of created relationships
+    */
+    public ArrayList<Relationship> getRelationshipList();
+    
+    /**
+    * Returns the length of the longest relationship name
+    * @return relationshipLength
+    */
+    public int getRelationshipLength();
+    
+    /**
+    * Updates relationshipLength
+    * @param newLen	| Length of new longest relationship name
+    */
+    public void setRelationshipLength(int newLen);
+    
+    /**
+    * Gets a ClassObject by the given name
+    * @param className		| The name of the class to return
+    * @return ClassObject with specified name if it exists
+    * 		   returns null if class does not exist
+    */
+    public ClassObject fetchClass(String className);
+    
+    /**
+    * Checks if a relationships exists
+    * @param source	| The source of the relationship
+    * @param dest		| Destination of the relationship
+    * @return True if relationship exists, false otherwise
+    */
+    public Relationship relationshipExist(String source, String dest);
+    
+    /**
+    * Iterates through relationships to find the longest name
+    * Used when deleting relationships
+    */
+    public void updateLongest();
+    
+    /**
+    * Creates a String listing classes and returns it
+    * @return String listing all classes and their info
+    */
+    public String listClasses();
+    
+    /**
+     * List the info of a specified class
+     * @param cls		| The class to be printed
+     * @return A String containing the list of specified class' info or 
+     * 		   empty string if class does not exist
      */
-public void setRelationshipLength(int newLen);
-
-/**
-     * Gets a ClassObject by the given name
-     * @param className The name of the class to return
-     * @return ClassObject with specified name if it exists
-     *    returns null if class does not exist
-     */
-public ClassObject fetchClass(String className);
-
-/**
-     * Checks if a relationships exists
-     * @param source The source of the relationship
-     * @param dest Destination of the relationship
-     * @return True if relationship exists, false otherwise
-     */
-public Relationship relationshipExist(String source, String dest);
-
-/**
-     * Iterates through relationships to find the longest name
-     * Used when deleting relationships
-     */
-public void updateLongest();
-
-/**
-     * Creates a String listing classes and returns it
-     * @return String listing all classes and their info
-     */
-public String listClasses();
-
-/**
- * List the info of a specified class
- * @param className The name of the class to be printed
- * @return A String containing the list of specified class' info or 
- *    empty string if class does not exist
- */
-public String listClassInfo(String className);
-
-/**
- * Lists all created relationships
- * @return A string containing a list of all relationships
- */
-public String listRelationships();
-
-/**
-     * Creates a list of all created class names that user can reference
-     * @return List of class names
-     */
-public String listClassNames();
-
-/**
-     * Creates a list of all created attributes in a given class
-     * @param className Class whose attributes are being listed
-     * @return A String of all attributes in the class
+    public String listClassInfo(ClassObject cls);
+    
+    /**
+     * Lists all created relationships
+     * @return A string containing a list of all relationships
      */
-public String listAttributes(String className);
+    public String listRelationships();
+    
+    /**
+    * Creates a list of all created class names that user can reference
+    * @return List of class names
+    */
+    public String listClassNames();
+    
+    /**
+    * Creates a list of all created fields in the given class
+    * 
+    * @param cls	| Class whose fields are being listed
+    * @return A string of all fields in the class
+    */
+   public String listFields(ClassObject cls);
+    
+    /**
+    * Creates a list of all created methods in the given class
+    * 
+    * @param cls	| Class whose methods are being listed
+    * @return A string containing all methods in the class
+    */
+   public String listMethods(ClassObject cls);
 }


Reviews:
user: login: N-ckM
body: assuming no compilation errors, this code looks good and header comments are provided in interface or within subclasses as they should be 👍 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-02T13:34:36Z
user: login: donut0711
body: I began writing this last night before it was merged but if some of the questions I ask here could be explaned to me that would be awesome.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-02T18:04:47Z
user: login: dpbrooks
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T15:01:26Z
user: login: dpbrooks
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T15:11:32Z
user: login: dpbrooks
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T15:13:40Z
user: login: dpbrooks
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T15:20:15Z
user: login: dpbrooks
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T15:26:15Z
user: login: dpbrooks
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T15:37:53Z
user: login: dpbrooks
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T15:43:46Z
user: login: dpbrooks
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T15:53:14Z
user: login: dpbrooks
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T15:56:27Z
user: login: donut0711
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T17:05:08Z
user: login: donut0711
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T17:09:11Z
user: login: donut0711
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T17:12:17Z
user: login: donut0711
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T17:14:38Z
user: login: donut0711
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T17:26:52Z

Review comments:
diff_hunk: @@ -1,22 +1,30 @@
 package org.Model;
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 
 //Creates a Class object
 public class ClassObject implements ClassObjectInterface {
 
-	//Name of a class
+	// Name of a class
 	private String name;
 
-	//Stores all attributes belonging to a class
-	private ArrayList<Attribute> attrList;
+	// Stores all attributes belonging to a class
+	private LinkedHashMap<String, ArrayList<AttributeInterface>> attrMap;
path: app/src/main/java/org/Model/ClassObject.java
user: login: donut0711
body: What is the advantage of this over just having a list for fields and methods.
created_at: 2025-03-02T05:02:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -30,32 +38,70 @@ public String getName() {
 	public void setName(String newName) {
 		this.name = newName;
 	}
+
+	/**
+	 * Gets the HashMap containing lists of fields and methods
+	 * @return HashMap containing ArrayLists of fields and methods
+	 */
+	public LinkedHashMap<String, ArrayList<AttributeInterface>> getAttrMap() {
path: app/src/main/java/org/Model/ClassObject.java
user: login: donut0711
body: This doesn't feel like something a consumer of this class should ever need. getFieldList() and getMethodList() cover every use case for this I can think of.
created_at: 2025-03-02T05:08:02Z
author_association: CONTRIBUTOR
path: app/src/main/java/org/Model/Parameter.java
user: login: donut0711
body: Dose this need to be it's own object since the data is just one String.
created_at: 2025-03-02T05:14:58Z
author_association: CONTRIBUTOR
path: app/src/main/java/org/Controller/UMLEditor.java
user: login: donut0711
body: I feel like the consumer of UMLEditor should be able to operate on classes by there name and not by passing in the classObject. If I have to get the ClassObject and AttributeObject for everything I want to do it would just be easer to call there methods directly.
created_at: 2025-03-02T05:50:43Z
author_association: CONTRIBUTOR
path: app/src/main/java/org/Model/AttributeInterface.java
user: login: donut0711
body: Why not have both fields and methods have different interfaces as they are pretty different.
created_at: 2025-03-02T06:12:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -30,32 +38,70 @@ public String getName() {
 	public void setName(String newName) {
 		this.name = newName;
 	}
+
+	/**
+	 * Gets the HashMap containing lists of fields and methods
+	 * @return HashMap containing ArrayLists of fields and methods
+	 */
+	public LinkedHashMap<String, ArrayList<AttributeInterface>> getAttrMap() {
+		return attrMap;
+	}
 	
 	/**
-	 * Gets the attribute list that correlates to this class object
+	 * Gets the ArrayList containing fields
+	 * @return ArrayList containing fields
 	 */
-	public ArrayList<Attribute> getAttrList() {
-		return attrList;
+	public ArrayList<AttributeInterface> getFieldList() {
+		return attrMap.get("Field");
+	}
+	
+	/**
+	 * Gets the ArrayList containing methods
+	 * @return ArrayList containing methods
+	 */
+	public ArrayList<AttributeInterface> getMethodList() {
+		return attrMap.get("Method");
 	}
 	
 	@Override
-	public void addAttribute(Attribute attr) {
-		attrList.add(attr);
+	public void addAttribute(AttributeInterface attr) {
path: app/src/main/java/org/Model/ClassObject.java
user: login: donut0711
body: what is the benefit of this over having addField and addMethod as that would give a cleaner interface and also mean you wouldn't have to expect the consumer to create the field and method object.
created_at: 2025-03-02T17:22:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -30,32 +38,70 @@ public String getName() {
 	public void setName(String newName) {
 		this.name = newName;
 	}
+
+	/**
+	 * Gets the HashMap containing lists of fields and methods
+	 * @return HashMap containing ArrayLists of fields and methods
+	 */
+	public LinkedHashMap<String, ArrayList<AttributeInterface>> getAttrMap() {
+		return attrMap;
+	}
 	
 	/**
-	 * Gets the attribute list that correlates to this class object
+	 * Gets the ArrayList containing fields
+	 * @return ArrayList containing fields
 	 */
-	public ArrayList<Attribute> getAttrList() {
-		return attrList;
+	public ArrayList<AttributeInterface> getFieldList() {
+		return attrMap.get("Field");
+	}
+	
+	/**
+	 * Gets the ArrayList containing methods
+	 * @return ArrayList containing methods
+	 */
+	public ArrayList<AttributeInterface> getMethodList() {
+		return attrMap.get("Method");
 	}
 	
 	@Override
-	public void addAttribute(Attribute attr) {
-		attrList.add(attr);
+	public void addAttribute(AttributeInterface attr) {
+		attrMap.get(attr.getType()).add(attr);
 	}
+	
 	@Override
-	public void removeAttribute(Attribute attr) {
-		attrList.remove(attr);
+	public void removeAttribute(AttributeInterface attr) {
path: app/src/main/java/org/Model/ClassObject.java
user: login: donut0711
body: what is benefit over different functions for field and method that take in a name. that feels much easier to use to me.
created_at: 2025-03-02T17:23:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,102 @@
+package org.Model;
+
+import java.util.ArrayList;
+
+public class Method implements AttributeInterface {
+
+	// Data Fields
+	private String name;
+	private String type;
+	private ArrayList<Parameter> paramList;
+	
+    /**
+	 * Constructor to create a new method
+	 * @param name			| The name of the method
+	 * @param paramList		| List of parameters the method contains
+	 */
+	public Method(String name, ArrayList<Parameter> paramList) {
+		this.name = name;
+		type = "Method";
+		this.paramList = paramList;
+	}
+	
+	@Override
+	public String getName() {
+		return name;
+	}
+	
+    @Override
+	public String getType() {
+		return type;
+	}
+	
+    /**
+	 * Returns the paramList of the method
+	 * @return The method's parameter list
+	 */
+	public ArrayList<Parameter> getParamList() {
+		return paramList;
+	}
+
+	@Override
+	public void renameAttribute(String newName) {
+		name = newName;
+	}
+	
+	/**
+	 * Concatenates the parameter list moreParams to the end of
+	 * paramList
+	 * @param moreParams	| List of params being added
+	 */
+	public void addParameter(ArrayList<Parameter> moreParams) {
path: app/src/main/java/org/Model/Method.java
user: login: donut0711
body: Why not take in a string and build a parameter. Also if you want to take in multiple at a time would it not be best to name the method addParameters.
created_at: 2025-03-02T17:54:30Z
author_association: CONTRIBUTOR
path: app/src/main/java/org/Model/UMLModel.java
user: login: donut0711
body: why not take in strings of the name of classes instead of the class object.
created_at: 2025-03-02T17:59:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,22 +1,30 @@
 package org.Model;
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 
 //Creates a Class object
 public class ClassObject implements ClassObjectInterface {
 
-	//Name of a class
+	// Name of a class
 	private String name;
 
-	//Stores all attributes belonging to a class
-	private ArrayList<Attribute> attrList;
+	// Stores all attributes belonging to a class
+	private LinkedHashMap<String, ArrayList<AttributeInterface>> attrMap;
path: app/src/main/java/org/Model/ClassObject.java
user: login: dpbrooks
body: Nick and I agreed it is cleaner to have them stored in a HashMap. This also allowed me to consolidate some code like add and remove attribute in the ClassObject by having it access the attrMap based on the attribute's type.
created_at: 2025-03-03T15:01:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -30,32 +38,70 @@ public String getName() {
 	public void setName(String newName) {
 		this.name = newName;
 	}
+
+	/**
+	 * Gets the HashMap containing lists of fields and methods
+	 * @return HashMap containing ArrayLists of fields and methods
+	 */
+	public LinkedHashMap<String, ArrayList<AttributeInterface>> getAttrMap() {
path: app/src/main/java/org/Model/ClassObject.java
user: login: dpbrooks
body: The attrMap is a private variable and needs a getter so that it can be accessed. Even if it isn't used right now I still think it is better to have a getter for it in the long run just in case.
created_at: 2025-03-03T15:11:32Z
author_association: CONTRIBUTOR
path: app/src/main/java/org/Model/Parameter.java
user: login: dpbrooks
body: Parameter is its own object like attributes were in the last sprint in case we need to expand on them in sprint 3. By making parameters their own object this will allow us to add more data fields to them without having to go back through and change how they are stored in case that is a requirement.
created_at: 2025-03-03T15:13:40Z
author_association: CONTRIBUTOR
path: app/src/main/java/org/Model/AttributeInterface.java
user: login: dpbrooks
body: Because fundamentally they are both split off of attributes from the first sprint(Fields are attributes and methods just have the added paramList). By having them both implement AttributeInterface this also allowed me to combine some methods and store both in the HashMap.
created_at: 2025-03-03T15:20:15Z
author_association: CONTRIBUTOR
path: app/src/main/java/org/Controller/UMLEditor.java
user: login: dpbrooks
body: The editor works on classes because all of the error checking occurs in the controller so that the system bails out at the first invalid input. Part of this error checking is calling fetchClass on the class name the user passes in to see if a class by that name exists. As fetchClass is being called in the controller we thought it would be best to pass the ClassObject into the editor instead of the name and calling fetchClass again. The same goes for methods and fields.
created_at: 2025-03-03T15:26:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -30,32 +38,70 @@ public String getName() {
 	public void setName(String newName) {
 		this.name = newName;
 	}
+
+	/**
+	 * Gets the HashMap containing lists of fields and methods
+	 * @return HashMap containing ArrayLists of fields and methods
+	 */
+	public LinkedHashMap<String, ArrayList<AttributeInterface>> getAttrMap() {
+		return attrMap;
+	}
 	
 	/**
-	 * Gets the attribute list that correlates to this class object
+	 * Gets the ArrayList containing fields
+	 * @return ArrayList containing fields
 	 */
-	public ArrayList<Attribute> getAttrList() {
-		return attrList;
+	public ArrayList<AttributeInterface> getFieldList() {
+		return attrMap.get("Field");
+	}
+	
+	/**
+	 * Gets the ArrayList containing methods
+	 * @return ArrayList containing methods
+	 */
+	public ArrayList<AttributeInterface> getMethodList() {
+		return attrMap.get("Method");
 	}
 	
 	@Override
-	public void addAttribute(Attribute attr) {
-		attrList.add(attr);
+	public void addAttribute(AttributeInterface attr) {
path: app/src/main/java/org/Model/ClassObject.java
user: login: dpbrooks
body: I did this to avoid having redundant functions. As methods and fields store their type I could designate the list to store them in with attrMap.get(attr.getType()). Also as they are both stored as AttributeInterfaces instead of their explicit types I felt having everything in one function was cleaner instead of splitting essentially the same thing between multiple functions.
created_at: 2025-03-03T15:37:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -30,32 +38,70 @@ public String getName() {
 	public void setName(String newName) {
 		this.name = newName;
 	}
+
+	/**
+	 * Gets the HashMap containing lists of fields and methods
+	 * @return HashMap containing ArrayLists of fields and methods
+	 */
+	public LinkedHashMap<String, ArrayList<AttributeInterface>> getAttrMap() {
+		return attrMap;
+	}
 	
 	/**
-	 * Gets the attribute list that correlates to this class object
+	 * Gets the ArrayList containing fields
+	 * @return ArrayList containing fields
 	 */
-	public ArrayList<Attribute> getAttrList() {
-		return attrList;
+	public ArrayList<AttributeInterface> getFieldList() {
+		return attrMap.get("Field");
+	}
+	
+	/**
+	 * Gets the ArrayList containing methods
+	 * @return ArrayList containing methods
+	 */
+	public ArrayList<AttributeInterface> getMethodList() {
+		return attrMap.get("Method");
 	}
 	
 	@Override
-	public void addAttribute(Attribute attr) {
-		attrList.add(attr);
+	public void addAttribute(AttributeInterface attr) {
+		attrMap.get(attr.getType()).add(attr);
 	}
+	
 	@Override
-	public void removeAttribute(Attribute attr) {
-		attrList.remove(attr);
+	public void removeAttribute(AttributeInterface attr) {
path: app/src/main/java/org/Model/ClassObject.java
user: login: dpbrooks
body: The remove function, works by designating an object to remove not a name, if I were using the object's name I would have to iterate through the arraylist to find an object that matches the name or name/parameter arity. This is already done in the controller when checking if the object exists to bail out early if invalid input is given. By passing in the object created after ensuring it exists, it allows the removeAttribute function in ClassObject to be that one line of code.
created_at: 2025-03-03T15:43:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,102 @@
+package org.Model;
+
+import java.util.ArrayList;
+
+public class Method implements AttributeInterface {
+
+	// Data Fields
+	private String name;
+	private String type;
+	private ArrayList<Parameter> paramList;
+	
+    /**
+	 * Constructor to create a new method
+	 * @param name			| The name of the method
+	 * @param paramList		| List of parameters the method contains
+	 */
+	public Method(String name, ArrayList<Parameter> paramList) {
+		this.name = name;
+		type = "Method";
+		this.paramList = paramList;
+	}
+	
+	@Override
+	public String getName() {
+		return name;
+	}
+	
+    @Override
+	public String getType() {
+		return type;
+	}
+	
+    /**
+	 * Returns the paramList of the method
+	 * @return The method's parameter list
+	 */
+	public ArrayList<Parameter> getParamList() {
+		return paramList;
+	}
+
+	@Override
+	public void renameAttribute(String newName) {
+		name = newName;
+	}
+	
+	/**
+	 * Concatenates the parameter list moreParams to the end of
+	 * paramList
+	 * @param moreParams	| List of params being added
+	 */
+	public void addParameter(ArrayList<Parameter> moreParams) {
path: app/src/main/java/org/Model/Method.java
user: login: dpbrooks
body: Michael and I have the parameters being built in the controller as we are checking if each user input is valid(Checking the paramList in the activeMethod and the new parameters that have already been written against the new input). We felt it was easier to build the parameters and store them in a list to use paramList.addAll() on as they were checked instead of storing their names and iterating through, building parameters, and adding them to the list one at a time inside the method function. You are definitely right about the name though and I will get that fixed, thanks for pointing that out.
created_at: 2025-03-03T15:53:14Z
author_association: CONTRIBUTOR
path: app/src/main/java/org/Model/UMLModel.java
user: login: dpbrooks
body: We are using fetchClass to check if a class exists and it returns a ClassObject if one exists or null if one does not. As we are editing properties of the classes, we felt it would be best to pass in the objects from the controller instead of calling fetchClass again.
created_at: 2025-03-03T15:56:27Z
author_association: CONTRIBUTOR
path: app/src/main/java/org/Controller/UMLEditor.java
user: login: donut0711
body: we have two controllers and this makes it so you have to rebuild all of that in the gui controller. The error checking for editing the model should happen in the editor. The editor should call fetchClass on the given string and if it returns not null it should throw an IllegalStateException. Having all of that in the consumer of the editor means the new gui and the filemanager have to remake all of that code for no benefit.
created_at: 2025-03-03T17:05:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -30,32 +38,70 @@ public String getName() {
 	public void setName(String newName) {
 		this.name = newName;
 	}
+
+	/**
+	 * Gets the HashMap containing lists of fields and methods
+	 * @return HashMap containing ArrayLists of fields and methods
+	 */
+	public LinkedHashMap<String, ArrayList<AttributeInterface>> getAttrMap() {
+		return attrMap;
+	}
 	
 	/**
-	 * Gets the attribute list that correlates to this class object
+	 * Gets the ArrayList containing fields
+	 * @return ArrayList containing fields
 	 */
-	public ArrayList<Attribute> getAttrList() {
-		return attrList;
+	public ArrayList<AttributeInterface> getFieldList() {
+		return attrMap.get("Field");
+	}
+	
+	/**
+	 * Gets the ArrayList containing methods
+	 * @return ArrayList containing methods
+	 */
+	public ArrayList<AttributeInterface> getMethodList() {
+		return attrMap.get("Method");
 	}
 	
 	@Override
-	public void addAttribute(Attribute attr) {
-		attrList.add(attr);
+	public void addAttribute(AttributeInterface attr) {
path: app/src/main/java/org/Model/ClassObject.java
user: login: donut0711
body: but it's wouldn't be redundant. addField and addMethod would ideally take in a string and build the object. I feel like this is the messiest way to do this as now checking if the method or field is unique and creating them have to be copy pasted all over the code base.
created_at: 2025-03-03T17:09:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,22 +1,30 @@
 package org.Model;
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 
 //Creates a Class object
 public class ClassObject implements ClassObjectInterface {
 
-	//Name of a class
+	// Name of a class
 	private String name;
 
-	//Stores all attributes belonging to a class
-	private ArrayList<Attribute> attrList;
+	// Stores all attributes belonging to a class
+	private LinkedHashMap<String, ArrayList<AttributeInterface>> attrMap;
path: app/src/main/java/org/Model/ClassObject.java
user: login: donut0711
body: using an if statement to check type would allow you to do the same thing without the overhead of a hash map.
created_at: 2025-03-03T17:12:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -30,32 +38,70 @@ public String getName() {
 	public void setName(String newName) {
 		this.name = newName;
 	}
+
+	/**
+	 * Gets the HashMap containing lists of fields and methods
+	 * @return HashMap containing ArrayLists of fields and methods
+	 */
+	public LinkedHashMap<String, ArrayList<AttributeInterface>> getAttrMap() {
path: app/src/main/java/org/Model/ClassObject.java
user: login: donut0711
body: it should never ever need to be accessed by an outside class the way it is now any consumer can put an arbitary key into your hash map since you return a reference and not a clone.
created_at: 2025-03-03T17:14:38Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,102 @@
+package org.Model;
+
+import java.util.ArrayList;
+
+public class Method implements AttributeInterface {
+
+	// Data Fields
+	private String name;
+	private String type;
+	private ArrayList<Parameter> paramList;
+	
+    /**
+	 * Constructor to create a new method
+	 * @param name			| The name of the method
+	 * @param paramList		| List of parameters the method contains
+	 */
+	public Method(String name, ArrayList<Parameter> paramList) {
+		this.name = name;
+		type = "Method";
+		this.paramList = paramList;
+	}
+	
+	@Override
+	public String getName() {
+		return name;
+	}
+	
+    @Override
+	public String getType() {
+		return type;
+	}
+	
+    /**
+	 * Returns the paramList of the method
+	 * @return The method's parameter list
+	 */
+	public ArrayList<Parameter> getParamList() {
+		return paramList;
+	}
+
+	@Override
+	public void renameAttribute(String newName) {
+		name = newName;
+	}
+	
+	/**
+	 * Concatenates the parameter list moreParams to the end of
+	 * paramList
+	 * @param moreParams	| List of params being added
+	 */
+	public void addParameter(ArrayList<Parameter> moreParams) {
path: app/src/main/java/org/Model/Method.java
user: login: donut0711
body: The editor would ideally build the parameters. If not then all of the code must be copy pasted around the code base everywhere a new parameter is needed to be added ie gui controler, and file manager.
created_at: 2025-03-03T17:26:52Z
author_association: CONTRIBUTOR

PR comments:
user: login: donut0711
created_at: 2025-03-02T18:39:53Z
body: also would have loved to see some tests written for the new classes
author_association: CONTRIBUTOR
user: login: dpbrooks
created_at: 2025-03-03T15:59:12Z
body: For tests, I noticed you had mentioned needing the fields and methods in a couple of your latest scrums so I focused on getting those done and pushed as soon as possible. I am currently working on finishing the tests and they should be done in a day or two. While I was working I thought of a couple more edge cases that I need to test for so once those get written I will push the tests.
author_association: CONTRIBUTOR