In this assignment you will be developing code to investigat

In this assignment, you will be developing code to investigate two important topics in genetics - restriction enzymes and DNA splicing. The Khan Academy has a straight-forward introduction to restriction enzymes and how they can be used to get E Coli bacteria to create insulin. The Howard Hughes Medical Institute also has an excellent animation of the process of splicing via restriction enzymes.

You will be developing a single Java class (LinkedDnaStrand) that uses a linked list of nodes to represent a strand of DNA that supports splicing. Each node in the list will contain a string of one or more nucleotides (A, C, G, or T). The class will be responsible for operations such as append() and cutSplice(), which model real-world restriction enzyme processing. To make the problem tractable, we will be making a number of assumptions that will simplify your work a lot - things like replacing rather than splitting the restriction enzyme. We are also going to be representing only one side of the DNA double-helix.

An illustration of the cut and splice operation on a linked list is shown below. In the diagram, a LinkedDnaStrand\'s linked list is shown just after it\'s constructor has been executed. The list is shown again after a call to cutSplice(). Note that each box in the diagram is an instance of DnaSequenceNode.

Getting Started

Naming is critical in the tasks and requirements described below. If the names don\'t match those described below exactly, your project will not compile and can\'t be graded.

Create a copy of the Java SE Project Template. The project name must follow this pattern: {FLname}_DnaSplicing_{TERM}, where {FLname} is replaced by the first letter of your first name plus your last name, and {TERM} is the semester and year. E.g. if your name is Maria Marciano and it\'s Fall of 2025, your project name must be MMarciano_DnaSplicing_F25.

Create a new package in the src folder called dnasplicing.

DnaSequenceNode

The LinkedDnaStrand class that you will be writing (see below) must use a DnaSequenceNode to hold each item in the linked list.

Save DnaSequenceNode.java (right-click | Save Link As...) into your dnasplicing package folder.

Refresh your project.

You do not modify DnaSequenceNode.java.

DnaStrand

The LinkedDnaStrand class that you will be writing (see below) must implement the DnaStrand interface.

Save DnaStrand.java (right-click | Save Link As...) into your dnasplicing package folder.

Refresh your project.

You will need to read the comments above each method declaration in DnaStrand.java to see what each method is supposed to do.

You do not modify DnaStrand.java. You will be adding your code to LinkedDnaStrand.java (see below).

LinkedDnaStrand

This is the class that you must write.

In the Package Explorer, select the dnasplicing package | New | Class.

In the wizard, set the name to LinkedDnaStrand. Then click the Add (interface) button, and search for DnaStrand. Check the \"Inherited abstract methods\" box. Click Finish. Eclipse will create the class and automatically add method stubs that meet the DnaStrand interface.

SimpleDnaStrand

SimpleDnaStrand is an array-based, inefficient implementation of DnaStrand. It is used by the grading script, LinkedDnaStrandTester, to verify that your code is giving correct output.

Save SimpleDnaStrand.java (right-click | Save Link As...) into your dnasplicing package folder.

Refresh your project.

The grading tester SimpleDnaStrand class that you will be writing (see below) must implement the DnaStrand interface.

You will need to read the comments above each method declaration in DnaStrand.java to see what each method is supposed to do.

You do not modify SimpleDnaStrand.java.

LinkedDnaStrandTester.

This is the grading script. It verifies that LinkedDnaStrand performs its operations correctly and efficiently.

Create a new package in the src folder called sbccunittest. To be clear:  sbccunittest should be a child of the src folder, not of the dnasplicing package.

Save LinkedDnaStrandTester.java (right-click Save Link As...) to the sbccunittest package.

You do not modify LinkedDnaStrandTester.java. And be sure that you don\'t accidentally allow Eclipse to modify it for you by accepting any Eclipse Quick Fixes that that it may offer that would change LinkedDnaStrandTester.

NOTE: LinkedDnaStrandTester should have compilation errors at this point. Not to worry - you\'ll be sorting those out below.

cutSplice() will only be called when the linked list has just one node, and it will only be called once for a DnaStrand. This means that you do not need to worry about searching for enzyme matches across node boundaries.

Feel free to add any additional methods, including constructors, that you need to implement the program.

Be sure to read the comments for each method in DnaStrand - they describe what your methods are supposed to do.

Also read the comments for the various tests in LinkedDnaStrandTester. They will help you understand what the test is trying to verify. It can also be very useful to read or step through the test code itself, as this will give the deepest insight into how your code is being graded.

StringUtils has a reverse() method that returns the reverse of a String.

The createReversedDnaStrand() method creates a new DnaStrand whose DNA sequence is a reverse of the original. So if a DnaStrand contains \"CGAT\", then createReversedDnaStrand() would return a DnaStrand that contains \"TAGC\". You will receive extra credit if the returned LinkDnaStrand contains a reversed version of both the DNA sequence and the nodes. E.g. if a LinkedDnaStrandcontained this linked list:

first -> \"TT\" -> \"TTAAGG\" -> \"CC\" -> null

then its reverese would be a new LinkedDnaStrand containing the following linked list:

first -> \"CC\" -> \"GGAATT\" -> \"TT\" -> null

Here are folders: https://drive.google.com/open?id=0B2gb5h869g2aM1lfSzlMTDBqYm8

SPL

Solution

package dnasplicing;

public interface DnaStrand {

   /**
   * NOTE: Your LinkedDnaStrand class must have a constructor that takes one parameter: String dnaSequence. When the
   * constructor completes, your linked list should have just one node, and it should contain the passed-in
   * dnaSequence. For example, if the following line of code was executed:
   *
   * LinkedDnaStrand strand = new LinkedDnaStrand(\"GATTACA\");
   *
   * Then strand\'s linked list should look something like (previous pointers not shown):
   *
   * first -> \"GATTACA\" -> null
   *
   * The first line of this constructor should look like:
   *
   * public LinkedDnaStrand(String dnaSequence) {
   */

   /**
   * @return The entire DNA sequence represented by this DnaStrand.
   */
   public String toString();


   /**
   * Returns the number of nucleotides in this strand.
   *
   * @return the number of base-pairs in this strand
   */
   public long getNucleotideCount();


   /**
   * Appends the given dnaSequence on to the end of this DnaStrand. appendCount is incremented. Note: If this
   * DnaStrand is empty, append() should just do the same thing as the constructor. In this special case, appendCount
   * is not incremented.
   *
   * @param dnaSequence
   *            is the DNA string to append
   */
   public void append(String dnaSequence);


   /**
   * This method creates a <bold>new</bold> DnaStrand that is a clone of the current DnaStrand, but with every
   * instance of enzyme replaced by splicee. For example, if the LinkedDnaStrand is instantiated with \"TTGATCC\", and
   * cutSplice(\"GAT\", \"TTAAGG\") is called, then the linked list should become something like (previous pointers not
   * shown):
   *
   * first -> \"TT\" -> \"TTAAGG\" -> \"CC\" -> null
   *
   * <b>NOTE</b>: This method will only be called when the linke list has just one node, and it will only be called
   * once for a DnaStrand. This means that you do not need to worry about searching for enzyme matches across node
   * boundaries.
   *
   * @param enzyme
   *            is the DNA sequence to search for in this DnaStrand.
   *
   * @param splicee
   *            is the DNA sequence to append in place of the enzyme in the returned DnaStrand
   *
   * @return A <bold>new</bold> strand leaving the original strand unchanged.
   */
   public DnaStrand cutSplice(String enzyme, String splicee);


   /**
   * Returns a <bold>new</bold> DnaStrand that is the reverse of this strand, e.g., if this DnaStrand contains \"CGAT\",
   * then the returned DnaStrand should contain \"TAGC\".
   *
   * @return A <bold>new</bold> strand containing a reversed DNA sequence.
   */
   public DnaStrand createReversedDnaStrand();


   /**
   *
   * @return The number of times that the DnaStrand has been appended via a call to append() or during the cutSplice()
   *         operation. Note that the very first time that a DnaStrand is given a DNA sequence is not to be counted as
   *         an append.
   */
   public int getAppendCount();


   /**
   * This is a utility method that allows the outside world direct access to the nodes in the linked list.
   *
   * @return The first DnaSequenceNode in the linked list of nodes.
   */
   public DnaSequenceNode getFirstNode();


   /**
   * This is a utility method that allows the outside world to determine the number of nodes in the linked list.
   *
   * @return
   */
   public int getNodeCount();

}


LinkedDnaStrand.java

package dnasplicing;

import org.apache.commons.lang3.*;

public class LinkedDnaStrand implements DnaStrand {

   private DnaSequenceNode top;
   private DnaSequenceNode current;
   private int count;
   private int appendCount;

   public LinkedDnaStrand() {
       top = null;
   }

   public LinkedDnaStrand(String dna) {
       if (count == 0)
           top = null;
       DnaSequenceNode newNode = new DnaSequenceNode(dna);
       newNode.next = top;
       if (top != null)
           top.previous = newNode;
       top = newNode;
       count++;

   }

   public String toString() {
       StringBuilder sb = new StringBuilder();

       DnaSequenceNode cursor = top;
       while (cursor != null) {
           sb.append(cursor.dnaSequence);
           cursor = cursor.next;
       }

       return sb.toString();
   }

   @Override
   public long getNucleotideCount() {
       String tempString = toString();
       return tempString.length();
   }

   @Override
   public void append(String dnaSequence) {
       if (dnaSequence.equals(\"\")) {
           return;
       }
       if (top == null) {
           DnaSequenceNode newNode = new DnaSequenceNode(dnaSequence);
           top = newNode;
           count++;
       } else {
           DnaSequenceNode newNode = new DnaSequenceNode(dnaSequence);
           current = top;
           while (current.next != null) {
               current = current.next;
           }
           current.next = newNode;
           current.next.previous = current;
           count++;
           appendCount++;
       }

   }

   @Override
   public DnaStrand cutSplice(String enzyme, String splicee) {

       int indexCursor = 0;
       int startIndex = 0;

       String tempString = toString();
       LinkedDnaStrand temp = new LinkedDnaStrand();

       while ((indexCursor = tempString.indexOf(enzyme, startIndex)) != -1) {
           temp.append(tempString.substring(startIndex, indexCursor));
           temp.append(splicee);
           startIndex = indexCursor + enzyme.length();
           indexCursor = startIndex;

       }
       if (tempString.substring(startIndex).length() > 0)
           temp.append(tempString.substring(startIndex));
       return temp;

   }

   @Override
   public DnaStrand createReversedDnaStrand() {
       LinkedDnaStrand temp = new LinkedDnaStrand();
       DnaSequenceNode current = top;
       while (current.next != null) {

           current = current.next;
       }
       while (current != null) {
           temp.append(StringUtils.reverse(current.dnaSequence));
           current = current.previous;
       }

       return temp;
   }

   @Override
   public int getAppendCount() {
       return appendCount;
   }

   @Override
   public DnaSequenceNode getFirstNode() {
       return top;
   }

   @Override
   public int getNodeCount() {
       return count;
   }

}

DnaSequenceNode.java

package dnasplicing;

public class DnaSequenceNode {
   public String dnaSequence;
   public DnaSequenceNode previous;
   public DnaSequenceNode next;


   public DnaSequenceNode(String initialDnaSequence) {
       dnaSequence = initialDnaSequence;
   }
}


SimpleDnaStrand.java

package dnasplicing;

public class SimpleDnaStrand implements DnaStrand {

   private StringBuilder nucleotides;

   private int appendCount;


   /**
   * Create a strand representing an empty DNA strand, length of zero.
   */
   public SimpleDnaStrand() {
       this(\"\");
   }


   /**
   * Create a strand representing dnaSequence. No error checking is done to see if s represents valid genomic/DNA
   * data.
   *
   * @param dnaSequence
   *            Initial DNA sequence for this strand
   */
   public SimpleDnaStrand(String dnaSequence) {
       nucleotides = new StringBuilder(dnaSequence);
   }


   public DnaStrand cutSplice(String enzyme, String splicee) {
       int pos = 0;
       int start = 0;
       StringBuilder search = nucleotides;
       boolean first = true;
       SimpleDnaStrand ret = null;

       /*
       * The next line is very syntax-dense. .indexOf looks for the first index at which enzyme occurs, starting at
       * pos. Saying pos = ... assigns the result of that operation to the pos variable; the value of pos is then
       * compared against zero.
       *
       * .indexOf returns -1 if enzyme can\'t be found. Therefore, this line is:
       *
       * \"While I can find enzyme, assign the location where it occurs to pos, and then execute the body of the loop.\"
       */
       while ((pos = search.indexOf(enzyme, pos)) >= 0) {
           if (first) {
               ret = new SimpleDnaStrand(search.substring(start, pos));
               first = false;
           } else {
               ret.append(search.substring(start, pos));

           }
           start = pos + enzyme.length();
           ret.append(splicee);
           pos++;
       }

       if (start < search.length()) {
           // NOTE: This is an important special case! If the enzyme
           // is never found, return an empty String.
           if (ret == null) {
               ret = new SimpleDnaStrand(\"\");
           } else {
               ret.append(search.substring(start));
           }
       }
       return ret;
   }


   /**
   * Initialize this strand so that it represents the value of source. No error checking is performed.
   *
   * @param source
   *            is the source of this enzyme
   */
   public void initialize(String dnaSequence) {
       nucleotides = new StringBuilder(dnaSequence);
   }


   /**
   * Returns the number of nucleotides/base-pairs in this strand.
   */
   public long getNucleotideCount() {
       return nucleotides.length();
   }


   @Override
   public String toString() {
       return nucleotides.toString();
   }


   /**
   * Append a strand of dna data to this strand.
   *
   * @param dnaSequence
   *            is the String appended to this strand
   */
   public void append(String dnaSequence) {
       nucleotides.append(dnaSequence);
       appendCount++;
   }


   public DnaStrand createReversedDnaStrand() {
       StringBuilder copy = new StringBuilder(nucleotides);
       SimpleDnaStrand ss = new SimpleDnaStrand();
       ss.nucleotides = copy;
       ss.nucleotides.reverse();
       return ss;
   }


   public int getAppendCount() {
       return appendCount;
   }


   @Override
   public DnaSequenceNode getFirstNode() {
       // Since this implementation does not contain a list of nodes, just return null.
       return null;
   }


   @Override
   public int getNodeCount() {
       // Since this implementation does not contain a list of nodes, just return 0.
       return 0;
   }

}

In this assignment, you will be developing code to investigate two important topics in genetics - restriction enzymes and DNA splicing. The Khan Academy has a s
In this assignment, you will be developing code to investigate two important topics in genetics - restriction enzymes and DNA splicing. The Khan Academy has a s
In this assignment, you will be developing code to investigate two important topics in genetics - restriction enzymes and DNA splicing. The Khan Academy has a s
In this assignment, you will be developing code to investigate two important topics in genetics - restriction enzymes and DNA splicing. The Khan Academy has a s
In this assignment, you will be developing code to investigate two important topics in genetics - restriction enzymes and DNA splicing. The Khan Academy has a s
In this assignment, you will be developing code to investigate two important topics in genetics - restriction enzymes and DNA splicing. The Khan Academy has a s
In this assignment, you will be developing code to investigate two important topics in genetics - restriction enzymes and DNA splicing. The Khan Academy has a s
In this assignment, you will be developing code to investigate two important topics in genetics - restriction enzymes and DNA splicing. The Khan Academy has a s

Get Help Now

Submit a Take Down Notice

Tutor
Tutor: Dr Jack
Most rated tutor on our site