Hi All,
Whilst there are many good examples on this forum that contain examples of coupling and cohesion, I am struggling to apply it to my code fully. I can identify parts in my code that may need changing. Would any Java experts be able to take a look at my code and explain to me what aspects are good and bad. I don't mind changing it myself at all. It's just that many people seem to disagree with each other and I'm finding it hard to actually understand what principles to follow...
package familytree;
/**
*
* @author David
*/
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
KeyboardInput in = new KeyboardInput();
FamilyTree familyTree = new FamilyTree(in, System.out);
familyTree.start();
}
}
package familytree;
import java.io.PrintStream;
/**
*
* @author David
*/
public class FamilyTree {
/**
* @param args the command line arguments
*/
private static final int DISPLAY_FAMILY_MEMBERS = 1;
private static final int ADD_FAMILY_MEMBER = 2;
private static final int REMOVE_FAMILY_MEMBER = 3;
private static final int EDIT_FAMILY_MEMBER = 4;
private static final int SAVE_FAMILY_TREE = 5;
private static final int LOAD_FAMILY_TREE = 6;
private static final int DISPLAY_ANCESTORS = 7;
private static final int DISPLAY_DESCENDANTS = 8;
private static final int QUIT = 9;
private KeyboardInput in;
private Family family;
private PrintStream out;
public FamilyTree(KeyboardInput in, PrintStream out) {
this.in = in;
this.out = out;
family = new Family();
}
public void start() {
out.println("\nWelcome to the Family Tree Builder");
//enterUserDetails();
initialise();
while (true) {
displayFamilyTreeMenu();
out.print("\nEnter Choice: ");
int option = in.readInteger();
if (option > 0 && option <= 8) {
if (quit(option)) {
break;
}
executeOption(option);
} else {
out.println("Invalid Choice!");
}
}
}
//good
private void displayFamilyTreeMenu() {
out.println("\nFamily Tree Menu");
out.println(DISPLAY_FAMILY_MEMBERS + ". Display Family Members");
out.println(ADD_FAMILY_MEMBER + ". Add Family Member");
out.println(REMOVE_FAMILY_MEMBER + ". Remove Family Member");
out.println(EDIT_FAMILY_MEMBER + ". Edit Family Member");
out.println(SAVE_FAMILY_TREE + ". Save Family Tree");
out.println(LOAD_FAMILY_TREE + ". Load Family Tree");
out.println(DISPLAY_ANCESTORS + ". Display Ancestors");
out.println(DISPLAY_DESCENDANTS + ". Display Descendants");
out.println(QUIT + ". Quit");
}
//good
private boolean quit(int opt) {
return (opt == QUIT) ? true : false;
}
//good
private void executeOption(int choice) {
switch (choice) {
case DISPLAY_FAMILY_MEMBERS:
displayFamilyMembers();
break;
case ADD_FAMILY_MEMBER:
addFamilyMember();
break;
case REMOVE_FAMILY_MEMBER:
break;
case EDIT_FAMILY_MEMBER:
break;
case SAVE_FAMILY_TREE:
break;
case LOAD_FAMILY_TREE:
break;
case DISPLAY_ANCESTORS:
displayAncestors();
break;
case DISPLAY_DESCENDANTS:
displayDescendants();
break;
default:
out.println("Not a valid option! Try again.");
break;
}
}
//for selecting family member for editing adding nodes etc
private void displayFamilyMembers() {
out.println("\nDisplay Family Members");
int count = 0;
for (FamilyMember member : family.getFamilyMembers()) {
out.println();
if (count + 1 < 10) {
out.println((count + 1) + ". " + member.getFirstName() + " " + member.getLastName());
out.println(" " + member.getDob());
out.println(" Generation: " + member.getGeneration());
} else {
out.println((count + 1) + ". " + member.getFirstName() + " " + member.getLastName());
out.println(" " + member.getDob());
out.println(" Generation: " + member.getGeneration());
}
count++;
}
}
private int selectRelative() {
out.println("\nSelect Relative");
out.println("1. Add Parents");
out.println("2. Add Child");
out.println("3. Add Partner");
out.println("4. Add Sibling");
out.print("\nEnter Choice: ");
int choice = in.readInteger();
if (choice > 0 && choice < 5) {
return choice;
}
return (-1);
}
private void addFamilyMember() {
int memberIndex = selectMember();
if (memberIndex >= 0) {
FamilyMember member = family.getFamilyMember(memberIndex);
int relative = selectRelative();
if (relative > 0) {
out.println("\nAdd Member");
//if choice is valid
switch (relative) {
case 1:
//adding parents
if (member.getFather() == null) {
FamilyMember mum, dad;
out.println("Enter Mothers Details");
mum = addMember(relative, "Female");
out.println("\nEnter Fathers Details");
dad = addMember(relative, "Male");
member.linkParent(mum);
member.linkParent(dad);
mum.linkPartner(dad);
mum.setGeneration(member.getGeneration() - 1);
dad.setGeneration(member.getGeneration() - 1);
sortGenerations();
} else {
out.println(member.getFirstName() + " " + member.getLastName() + " already has parents.");
}
break;
case 2:
//adding child
if (member.getPartner() == null) {
FamilyMember partner;
if (member.getGender().equals("Male")) {
out.println("Enter Mothers Details");
partner = addMember(1, "Female");
} else {
out.println("Enter Fathers Details");
partner = addMember(1, "Male");
}
//create partner
member.linkPartner(partner);
partner.setGeneration(member.getGeneration());
out.println();
}
out.println("Enter Childs Details");
FamilyMember child = addMember(relative, "");
child.linkParent(member);
child.linkParent(member.getPartner());
child.setGeneration(member.getGeneration() + 1);
sortGenerations();
break;
case 3:
//adding partner
if (member.getPartner() == null) {
out.println("Enter Partners Details");
FamilyMember partner = addMember(relative, "");
member.linkPartner(partner);
partner.setGeneration(member.getGeneration());
} else {
out.println(member.getFirstName() + " " + member.getLastName() + " already has a partner.");
}
break;
case 4:
//adding sibling
FamilyMember mum,
dad;
if (member.getFather() == null) {
out.println("Enter Mothers Details");
mum = addMember(1, "Female");
out.println("\nEnter Fathers Details");
dad = addMember(1, "Male");
member.linkParent(mum);
member.linkParent(dad);
mum.linkPartner(dad);
mum.setGeneration(member.getGeneration() - 1);
dad.setGeneration(member.getGeneration() - 1);
sortGenerations();
out.println("\nEnter Siblings Details");
} else {
out.println("Enter Siblings Details");
}
FamilyMember sibling = addMember(relative, "");
//create mum and dad
mum = member.getMother();
dad = member.getFather();
sibling.linkParent(mum);
sibling.linkParent(dad);
sibling.setGeneration(member.getGeneration());
break;
}
} else {
out.println("Invalid Option!");
}
} else {
out.println("Invalid Option!");
}
}
private int selectMember() {
displayFamilyMembers();
out.print("\nSelect Member: ");
int choice = in.readInteger();
if (choice > 0 && choice <= family.getFamilyMembers().size()) {
return (choice - 1);
}
return -1;
}
private FamilyMember addMember(int option, String gender) {
out.print("Enter First Name: ");
String fName = formatString(in.readString().trim());
out.print("Enter Last Name: ");
String lName = formatString(in.readString().trim());
if (option != 1) { //if not adding parents
out.println("Select Gender");
out.println("1. Male");
out.println("2. Female");
out.print("Enter Choice: ");
int gOpt = in.readInteger();
if (gOpt == 1) {
gender = "Male";
} else if (gOpt == 2) {
gender = "Female";
} else {
out.println("Invalid Choice");
return null;
}
}
String dob = enterDateOfBirth();
lName = formatString(lName);
FamilyMember f = family.getFamilyMember(family.addMember(fName, lName, gender, dob));
f.setIndex(family.getFamilyMembers().size() - 1);
return (f);
}
private String formatString(String s){
String firstLetter = s.substring(0, 1);
String remainingLetters = s.substring(1, s.length());
s = firstLetter.toUpperCase() + remainingLetters.toLowerCase();
return s;
}
private String enterDateOfBirth(){
out.print("Enter Year Of Birth (0 - 2011): ");
String y = in.readString();
out.print("Enter Month Of Birth (1-12): ");
String m = in.readString();
if (Integer.parseInt(m) < 10) {
m = "0" + m;
}
m += "-";
out.print("Enter Date of Birth (1-31): ");
String d = in.readString();
if (Integer.parseInt(d) < 10) {
d = "0" + d;
}
d += "-";
String dob = d + m + y;
while(!DateValidator.isValid(dob)){
out.println("Invalid Date. Try Again:");
dob = enterDateOfBirth();
}
return (dob);
}
private void displayAncestors() {
out.print("\nDisplay Ancestors For Which Member: ");
int choice = selectMember();
if (choice >= 0) {
FamilyMember node = family.getFamilyMember(choice );
FamilyMember ms = findRootNode(node, 0, 2, -1);
FamilyMember fs = findRootNode(node, 1, 2, -1);
out.println("\nPrint Ancestors");
out.println("\nMothers Side");
printDescendants(ms, node, ms.getGeneration());
out.println("\nFathers Side");
printDescendants(fs, node, fs.getGeneration());
} else {
out.println("Invalid Option!");
}
}
private void displayDescendants() {
out.print("\nDisplay Descendants For Which Member: ");
int choice = selectMember();
if (choice >= 0) {
FamilyMember node = family.getFamilyMember(choice);
out.println("\nPrint Descendants");
printDescendants(node, null, 0);
} else {
out.println("Invalid Option!");
}
}
private FamilyMember findRootNode(FamilyMember node, int parent, int numGenerations, int count) {
FamilyMember root;
count++;
if (node.hasParents() && count < numGenerations) {
if (parent == 0) {
node = node.getMother();
root = findRootNode(node, 1, numGenerations, count);
} else {
node = node.getFather();
root = findRootNode(node, 1, numGenerations, count);
}
return root;
}
return node;
}
private int findHighestLeafGeneration(FamilyMember node) {
int gen = node.getGeneration();
for (int i = 0; i < node.getChildren().size(); i++) {
int highestChild = findHighestLeafGeneration(node.getChild(i));
if (highestChild > gen) {
gen = highestChild;
}
}
return gen;
}
private void printDescendants(FamilyMember root, FamilyMember node, int gen) {
out.print((root.getGeneration() + 1) + " " + root.getFullName());
out.print(" [" + root.getDob() + "] ");
if (root.getPartner() != null) {
out.print("+Partner: " + root.getPartner().getFullName() + " [" + root.getPartner().getDob() + "] ");
}
if (root == node) {
out.print("*");
}
out.println();
if (!root.getChildren().isEmpty() && root != node) {
for (int i = 0; i < root.getChildren().size(); i++) {
for (int j = 0; j < root.getChild(i).getGeneration() - gen; j++) {
out.print(" ");
}
printDescendants(root.getChild(i), node, gen);
}
} else {
return;
}
}
//retrieve highest generation
public int getRootGeneration(){
int min = family.getFamilyMember(0).getGeneration();
for(int i = 0; i < family.getFamilyMembers().size(); i++){
min = Math.min(min, family.getFamilyMember(i).getGeneration());
}
return Math.abs(min);
}
public void sortGenerations(){
int amount = getRootGeneration();
for (FamilyMember member : family.getFamilyMembers()) {
member.setGeneration(member.getGeneration() + amount);
}
}
//test method - temporary
private void initialise() {
family.addMember("Bilbo", "Baggins", "Male", "23-06-1920");
}
}
package familytree;
import java.util.ArrayList;
import java.util.Date;
/**
*
* @author David
*/
public class Family {
//family members
private ArrayList<FamilyMember> family;
//create Family
public Family() {
family = new ArrayList<FamilyMember>();
}
//add member to the family
public int addMember(String f, String l, String g, String d) {
family.add(new FamilyMember(f, l, g, d));
return family.size()-1;
}
//remove member from family
public void removeMember(int index) {
family.remove(index);
}
public FamilyMember getFamilyMember(int index) {
return family.get(index);
}
//return family
public ArrayList <FamilyMember> getFamilyMembers() {
return family;
}
public void changeFirstName(int index, String f) {
family.get(index).setFirstName(f);//change to setfirstname and others
}
public void changeLastName(int index, String l) {
family.get(index).setLastName(l);
}
public void changeAge(int index, int a) {
family.get(index).setAge(a);
}
public void changeDOB() {
//implement
}
}
package familytree;
import java.util.ArrayList;
import java.util.Collections;
/**
*
* @author David
*/
public class FamilyMember extends Person {
private FamilyMember mother;
private FamilyMember father;
private FamilyMember partner;
private ArrayList<FamilyMember> children;
private int generation;
private int index;
//initialise family member
public FamilyMember(String f, String l, String g, String d) {
super(f, l, g, d);
mother = null;
father = null;
partner = null;
children = new ArrayList<FamilyMember>();
generation = 0;
index = -1;
}
public void linkParent(FamilyMember parent) {
if (parent.getGender().equals("Female")) {
this.setMother(parent);
} else {
this.setFather(parent);
}
parent.addChild(this);
}
public void linkPartner(FamilyMember partner) {
partner.setPartner(this);
this.setPartner(partner);
}
public boolean hasParents() {
if (this.getMother() == null && this.getFather() == null) {
return false;
}
return true;
}
public FamilyMember getMother() {
return mother;
}
public FamilyMember getFather() {
return father;
}
public FamilyMember getPartner() {
return partner;
}
public FamilyMember getChild(int index) {
return children.get(index);
}
public int getGeneration() {
return generation;
}
public int getIndex() {
return index;
}
public ArrayList<FamilyMember> getChildren() {
return children;
}
public void setMother(FamilyMember f) {
mother = f;
}
public void setFather(FamilyMember f) {
father = f;
}
public void setPartner(FamilyMember f) {
partner = f;
}
public void addChild(FamilyMember f) {
children.add(f); //add child
if(children.size() > 1){
//sort in ascending order
Collections.sort(children, new DateComparator());
}
}
public void addChildAt(FamilyMember f, int index) {
children.set(index, f);
}
public void setGeneration(int g) {
generation = g;
}
public void setIndex(int i){
index = i;
}
}
package familytree;
/**
*
* @author David
*/
public class Person{
private String fName;
private String lName;
private String gender;
private int age;
private String dob;
public Person(String fName, String lName, String gender, String dob){
this.fName = fName;
this.lName = lName;
this.gender = gender;
this.dob = dob;
}
public String getFullName(){
return (this.fName + " " + this.lName);
}
public String getFirstName(){
return (fName);
}
public String getLastName(){
return (lName);
}
public String getGender(){
return (gender);
}
public String getDob(){
return dob;
}
public int getAge(){
return age;
}
public void setFirstName(String fName){
this.fName = fName;
}
public void setLastName(String lName){
this.lName = lName;
}
public void setGender(String gender){
this.gender = gender;
}
public void setAge(int age){
this.age = age;
}
}