CSE-8B / PA9 / starter / MyStringBuilder.java
MyStringBuilder.java
Raw
//File: MyStringBuilder.java
//Name: Trai Pham
//Date: 03/09/2020
//Course: CSE 8B
/**
MyStringBuilder class contains all the methods that can manipulate a string
**/
public class MyStringBuilder{
  protected CharNode start;
  protected CharNode end;
  protected int length;
  public String emptyStr ="";
  public String spaceStr = " ";

/**
@param char variable
@return nothing
Constructor
**/
  public MyStringBuilder(char a){
    this.length++;
    this.start = new CharNode(a);
    this.end = this.start;
  }

/**
@param String variable
@return nothing
Constructor
**/
  public MyStringBuilder(String str) throws BadInputException{
    try{
    if(str == null){
      throw new BadInputException(Constants.FROM_CONSTRUCTOR,
      "bad input exception");
    }
//sets the charNode of the obj to null for empty strings
    else if(str == emptyStr){
      this.start = null;
      this.end = null;
      this.length = 0;
    }
    else{
//adding charNode letter by letter
      this.length++;
      this.start = new CharNode(str.charAt(0));
      this.end = this.start;
      for(int i =1; i < str.length(); i++){
        this.append(str.charAt(i));
      }
    }
  }
    catch(BadInputException badInputEx){
      System.out.println(badInputEx.getMessage());
  }
  }

/**
@param MyStringBuilder object
@return nothing
Constructor
**/
  public MyStringBuilder(MyStringBuilder obj) throws BadInputException{
    try{
      if(obj == null){
        throw new BadInputException(Constants.FROM_DEEPCOPY_CONSTRUCTOR,
          "bad input Exception");
      }
      else{
//setting the first and last node with the object in the input
        this.length = obj.length();
        this.start = obj.start;
        this.end = new CharNode(this.start.getData());
        CharNode currNode = this.start.setNext(obj.start.getNext());
//goes through the references and nodes of the inputted obj
        for(int i = 1; i < this.length; i++){
          CharNode newNode = new CharNode(currNode.getData());
          this.end = newNode;
          newNode = currNode.setNext(currNode.getNext());
          currNode = newNode;
        }
      }
    }
    catch(BadInputException badInputEx){
      System.out.println(badInputEx.getMessage());
    }
  }

/**
@param nothing
@return int
gets length
**/
  public int length(){
    return this.length;
  }

/**
@param char variable
@return MyStringBuilder object
This will add an additional charNode to the myStrinbBuilder object, that
contains the character c
**/
  public MyStringBuilder append(char c){
    if(this.start == null && this.end == null){
      this.start = new CharNode(c);
      this.end = this.start;
    }
    else{
//this would create a new CharNode object with the char
      CharNode newNext = new CharNode(c);
//this sets the next reference CharNode obj to the new Charnode obj
      this.end = this.end.setNext(newNext);
//setting the last Charnode obj to the new
      this.end = newNext;
      this.length++;
    }
    return this;
  }

/**
@param String variable
@return MyStringBuilder
This will add a String to the MyStringBuilder, in which we're adding additional
CharNodes to the called object.
**/
  public MyStringBuilder append(String str) throws BadInputException{
    try{
      if(str == null || str== spaceStr){
        throw new BadInputException(Constants.FROM_APPEND_STR,
        "bad input Exception");
      }
//this will return the original string since an empty string is added
      if(str == emptyStr){
        return this;
      }
      else{
//this will add the String to the object, adding to it CharNode by CharNode
        for(int i = 0; i< str.length(); i++){
          this.append(str.charAt(i));
        }
      }
    }
    catch(BadInputException badInputEx){
      System.out.println(badInputEx.getMessage());
    }
    return this;
  }

/**
@param nothing
@return String
A to String method that would allow us to print out the MyStringBuilder object
**/
  public String toString(){
    if(this.start == null){
      return emptyStr;
    }
//this will add the characters together in the CharNode
    String result = emptyStr;
    CharNode currNode = this.start;
    for(int i = 0; i < this.length(); i++){
      result = result + Character.toString(currNode.getData());
      currNode = currNode.getNext();
    }
    return result;
  }

/**
@param char variable, int variable
@return MyStringBuilder object
inserting a character in a specific index within the object, which we're
pushing the previous node at the index to the right, and shifting the other
CharNodes after the index will be shifting to the right
**/
  public MyStringBuilder insert(char c, int index) throws
  MSBOutOfBoundsException{
    try{
      if(index > this.length() || index < 0){
        throw new MSBOutOfBoundsException(Constants.FROM_INSERT_CHAR,
        "MSB Out of Bound Exception");
      }
//inserting the character at the very beginning of the object
      else if(index == 0){
        CharNode newNode = new CharNode(c);
        newNode = newNode.setNext(this.start);
        this.start = newNode;
        this.length++;
      }
//this will insert the character to a space after the last Node
      else if(index == this.length){
        CharNode newNext = new CharNode(c);
        this.end = this.end.setNext(newNext);
        this.end = newNext;
        this.length++;
      }
//this will insert a character within the bounds of the first node and the last
//node
      else if(index > 0 && index < this.length){
        CharNode newNode = new CharNode(c);
        CharNode newCurrNode = this.start;
        CharNode currNode = this.start;
//this iterates till the index
        for(int i = 1; i < index; i++){
          currNode = currNode.getNext();
        }
//iterates till the index
        for(int j = 1; j <= index; j++){
          newCurrNode = newCurrNode.getNext();
        }
//adds the next node of the currNode to that of the added CharNodes
// and link the new added CharNode to that of the next CharNode
        currNode = currNode.setNext(newNode);
        newNode = newNode.setNext(newCurrNode);
        this.length++;
      }
    }
    catch(MSBOutOfBoundsException msbEx){
      System.out.println(msbEx.getMessage());
    }
    return this;
  }

/**
@param String variable, and int index
@return MyStringBuilder object
This will insert an entire String at a specific index, shifting every other
Charnode after that index to the right
**/
  public MyStringBuilder insert (String str, int index) throws
  BadInputException, MSBOutOfBoundsException{
    try{
      if(str == null){
        throw new BadInputException(Constants.FROM_INSERT_STR,
        "Bad input exception");
      }
      if(index > this.length() || index < 0){
        throw new MSBOutOfBoundsException(Constants.FROM_INSERT_STR,
          "MSB Out of Bound Exception");
      }
//when the index starts at the beginning of the object, the entire sstring will
//be at the start of the object
      else if(index == 0){
        for(int i =0 ; i < str.length(); i++){
          this.insert(str.charAt(i),i);
        }
      }
//this will insert a string at a certain index in between the start and end of
//the MyStringBuilder object
      else if(index > 0 && index < this.length){
        for(int i =0; i < str.length(); ++i){
          this.insert(str.charAt(i), index+i);
        }
      }
//this will add the string to the very end of the MyStringBuilder object
      else if(index == this.length){
        for(int i =0; i < str.length(); i++){
          this.insert(str.charAt(i), index+i);
        }
      }
    }
    catch(BadInputException badInputEx){
      System.out.println(badInputEx.getMessage());
    }
    catch(MSBOutOfBoundsException msbEx){
      System.out.println(msbEx.getMessage());
    }
    return this;
  }

/**
@param int index
@return CharNode
Finds CharNode at an index in the object
**/
  protected CharNode findIndex(int index) throws MSBOutOfBoundsException{
    CharNode currNode = this.start;
    try{
      if(this.start == null && this.end == null){
        throw new MSBOutOfBoundsException(Constants.FROM_FIND_INDEX,
        "Out of Bound");
      }
      if(index < 0 || index >= this.length){
        throw new MSBOutOfBoundsException(Constants.FROM_FIND_INDEX,
        "Out of Bound");
      }
    }
    catch(MSBOutOfBoundsException msbEx){
      System.out.println(msbEx.getMessage());
    }
//when the index is 0, it'll return the first CharNode
    if(index == 0){
      return this.start;
    }
//Iterates till index, returns the CharNode at that index
    else{
      for(int i = 1; i <= index; i++){
        currNode = currNode.getNext();
      }
      return currNode;
    }
  }

/**
@param int index
@return MyStringBuilder object
remove the CharNode at a certain index
**/
  public MyStringBuilder remove (int index) throws MSBOutOfBoundsException{
    try{
      if(index < 0 || index >= this.length){
        throw new MSBOutOfBoundsException(Constants.FROM_REMOVE,
        "Out of Bound");
      }
//when the index is 0, this will remove the first index of the object called
      else if(index == 0){
        CharNode nextNode = this.start.getNext();
        this.start = nextNode;
        this.length--;
        return this;
      }
//when the index is between the first index and the last index, it'll remove
//the CharNode within that boundary
      else if (index > 0 && index < this.length-1){
        CharNode prevNode = this.start;
        CharNode nextNode = this.start;
//iterates till the index
        for(int a  = 1; a < index; a++){
          prevNode = prevNode.getNext();
        }
//iterates till the index, including the index
        for(int c = 1; c <= index + 1; c++){
          nextNode = nextNode.getNext();
        }
//this will connect the prevNode to that of the Next Node, which would Remove
//the CharNode inbetween the two nodes
        prevNode = prevNode.setNext(nextNode);
        this.length--;
        return this;
      }
//When removing the last index of the called object, we're iterating to the
//very end of object, and make the last index to the previous node
      else if(index == this.length-1){
        CharNode currNode = this.start;
        for(int i =1; i < this.length; i++){
          currNode = currNode.getNext();
        }
        this.end = this.end.setNext(currNode);
        this.length--;
        return this;
      }
    }
    catch(MSBOutOfBoundsException msbEx){
      System.out.println(msbEx.getMessage());
    }
    return this;
  }

/**
@param int index
@return MyStringBuilder object
this will delete everything after the index
**/
  public MyStringBuilder delete (int startIndex) throws MSBOutOfBoundsException{
    try{
      if(startIndex < 0 || startIndex >= this.length){
        throw new MSBOutOfBoundsException(Constants.FROM_DELETE_STARTINDEX,
        "Out Of Bound");
      }
//deleting all the CharNodes from the entire object
      else if(startIndex ==0){
        this.end = this.end.setNext(this.start);
        this.length = startIndex;
        return this;
      }
//removing the CharNodes within the boundaries of the starting index to last
//index
      else if(startIndex > 0 && startIndex <this.length){
        CharNode currNode = this.start;
        for(int i = 0; i < startIndex; i++){
          currNode = currNode.getNext();
        }
        this.end = this.end.setNext(currNode);
        this.length = startIndex;
        return this;
      }
//removing the last Charnode of the object
      else if(startIndex == this.length-1){
        CharNode currNode = this.start;
        for(int i = 0; i < startIndex; i++){
          currNode = currNode.getNext();
        }
//sets the last index to a different CharNode
        this.end = this.end.setNext(currNode);
        this.length = startIndex;
        return this;
      }
    }
    catch(MSBOutOfBoundsException msbEx){
      System.out.println(msbEx.getMessage());
    }
    return this;
  }

/**
@param int start of index, int end of index
@return MyStringBuilder object
deletes the CharNodes between the start Index and the end Index, though we're
not entirely deleting the CharNode, just changing the reference CharNodes
**/
  public MyStringBuilder delete (int startIndex, int endIndex) throws
  BadInputException, MSBOutOfBoundsException{
    try{
      if(startIndex < 0 || endIndex < 0 || endIndex > this.length ||
      startIndex >= this.length){
        throw new MSBOutOfBoundsException(
        Constants.FROM_DELETE_STARTINDEX_ENDINDEX,"Out Of Bound");
      }
      if(endIndex < startIndex){
        throw new BadInputException(Constants.FROM_DELETE_STARTINDEX_ENDINDEX,
        "Out Of Bound");
      }
//this will return the original MyStringBuilder without any edits
      else if(startIndex == endIndex){
        return this;
      }
      else{
//this will iterate from the start Index til the end index
        CharNode currNode = this.start;
        CharNode nextNode = this.start;
        for(int i = 1; i < startIndex; i++){
          currNode = currNode.getNext();
        }
        for(int i =1; i <= endIndex; i++){
          nextNode = nextNode.getNext();
        }
/**this will connect the CharNodes together, including the end Index in This
this will connect the CharNode from the start index, to the charNode of the
end Index
**/
        currNode = currNode.setNext(nextNode);
        this.length = this.length - (endIndex-startIndex);
        return this;
      }
    }
    catch(BadInputException badInputEx){
      System.out.println(badInputEx.getMessage());
    }
    catch(MSBOutOfBoundsException msbEx){
      System.out.println(msbEx.getMessage());
    }
    return this;
  }

/**
@param int index
@return String
This substring includes the character(s) from start index to the end charNode
of the MyStringBuilder object
**/
  public String substring(int startIndex) throws MSBOutOfBoundsException{
    String result = emptyStr;
    try{
      if(startIndex < 0 || startIndex >= this.length){
        throw new MSBOutOfBoundsException(Constants.FROM_SUBSTRING_STARTINDEX,
        "Out Of Bound");
      }
//this will iterate through the MyStringBuilder object til the start index
      else{
        CharNode currNode = this.start;
        for(int i = 0; i < startIndex; i++){
          currNode = currNode.getNext();
        }
//this is when we start grabbing the data from the startIndex to the very end
//of the MyStringBuilder object
        for(int j = startIndex; j < this.length; j++){
          result = result + Character.toString(currNode.getData());
          currNode = currNode.getNext();
        }
        return result;
      }
    }
    catch(MSBOutOfBoundsException msbEx){
      System.out.println(msbEx.getMessage());
    }
    return result;
  }

/**
@param MyStringBuilder object
@return nothing
subString method that takes away the startIndex to the endIndex but not
including the end index.
**/
  public String substring(int startIndex, int endIndex) throws
  MSBOutOfBoundsException, BadInputException{
    String result = emptyStr;
    try{
      if(startIndex < 0 || endIndex < 0 || endIndex > this.length ||
      startIndex >= this.length){
        throw new MSBOutOfBoundsException(
        Constants.FROM_SUBSTRING_STARTINDEX_ENDINDEX,"Out Of Bound");
      }
      if(endIndex < startIndex){
        throw new BadInputException(
        Constants.FROM_SUBSTRING_STARTINDEX_ENDINDEX,"Out Of Bound");
      }
//a empty string will be returned if the start index and end index are the same
      else if(startIndex == endIndex){
        return result;
      }
      else{
//this will go through the reference from the zero index of the MyStringBuilder
//object, and will continue to iterate til the CharNode before the start index
        CharNode currNode = this.start;
        for(int i =0; i < startIndex; i++){
          currNode=currNode.getNext();
        }
//starts adding the characters between startIndex and end Index, including
//start index
        for(int j = startIndex; j < endIndex; j++){
          result = result + Character.toString(currNode.getData());
          currNode = currNode.getNext();
        }
        return result;
      }
    }
    catch(BadInputException badInputEx){
      System.out.println(badInputEx.getMessage());
    }
    catch(MSBOutOfBoundsException msbEx){
      System.out.println(msbEx.getMessage());
    }
    return result;
  }

/**
@param MyStringBuilder second obj
@return MyStringBuilder obj
adds a new MyStringBuilder obj to the current MyStringBuilder obj
**/
  public MyStringBuilder concat(MyStringBuilder rightOperand) throws
  BadInputException{
    try{
      if(rightOperand == null){
        throw new BadInputException(Constants.FROM_CONCAT,
        "Bad Input Exception");
      }
//we set the first and end CharNode of the second obj to that of the called
//object
      if(this.length == 0){
        this.start = rightOperand.start;
        this.end = rightOperand.end;
        this.length = rightOperand.length();
        return this;
      }
//we connect the end CharNode of the called object to the start CharNode of the
//inputted object
      else{
        this.end = this.end.setNext(rightOperand.start);
        this.end = rightOperand.end;
        this.length = this.length + rightOperand.length();
        return this;
      }
    }
    catch(BadInputException badInputEx){
      System.out.println(badInputEx.getMessage());
    }
    return this;
  }

//TESTING THE PROGRAM!!!!

//   public static void main(String[] args){
//     String testStr = "testing";
//     String divider = "_________";
// try{
//     MyStringBuilder word = new MyStringBuilder('r');
//     System.out.println("Testing regular toString char");
//     System.out.println(word);
// //testing ToString with obj Constructor
//     MyStringBuilder someWord = new MyStringBuilder("something");
//     System.out.println("_________ testing Constructor(obj)");
//     MyStringBuilder newWord = new MyStringBuilder(someWord);
//     System.out.println(newWord.toString());
// //testing insert()
//     MyStringBuilder insertTest = new MyStringBuilder("rest");
//     System.out.println("___________ testing insert(Char)");
//     insertTest.insert('e', 3);
//     System.out.println(insertTest);
//     System.out.println("length of InsertTest=" + insertTest.length);
//     System.out.println("All insert boundary cases worked!!!");
//     System.out.println(divider);
//     insertTest.insert("best", 2);
//     System.out.println(insertTest);
//     System.out.println("InsertTest(String) Good!");
//   }
//   catch(BadInputException ex){}
// //testing ToString method
//   catch(MSBOutOfBoundsException ex){}
//     System.out.println("______________Append(string)");
// //testing append(string)
//   try{
//     MyStringBuilder extra = new MyStringBuilder("Coming");
//     extra.append("Home");
//     System.out.println("Append(String) length=" + extra.length);
//     System.out.println(extra.toString());
//     System.out.println(divider + "FindIndex(Int) return CharNode");
//     System.out.println(extra.findIndex(9).getData());
//     System.out.println(divider + "Remove(int index)");
//     System.out.println(extra.remove(0));
//     System.out.println("length=" + extra.length());
//     System.out.println(divider + "Delete(int starterIndex)");
//     System.out.println(extra.delete(5));
//     System.out.println(divider + "Delete(int start, int end)");
//     System.out.println(extra.delete(2,2));
//     System.out.println(divider + "Substring(int start)");
//     System.out.println(extra.substring(2));
//     System.out.println(divider + "Substring(int start, int end)");
//     System.out.println(extra.substring(0, 4));
//     System.out.println(divider + "Concat(obj MyStringBuilder)");
//     MyStringBuilder credit = new MyStringBuilder("together");
//     // System.out.println(credit);
//     // extra.concat(credit);
//     // System.out.println(extra);
//     MyStringBuilder a = new MyStringBuilder("");
//     MyStringBuilder b = new MyStringBuilder("bob");
//     a.concat(b);
//     System.out.println(a);
//   }
//   catch(MSBOutOfBoundsException msbEx){}
//   catch(BadInputException badInputEx){}
//
// }


}