package aliview.sequences; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import org.apache.commons.lang.ArrayUtils; import org.apache.log4j.Logger; import aliview.NucleotideUtilities; import aliview.utils.ArrayUtilities; public class DefaultBases implements Bases { private static final Logger logger = Logger.getLogger(DefaultBases.class); private static final String TEXT_FILE_BYTE_ENCODING = "ASCII"; byte[] backend; public DefaultBases(byte[] bytes) { this.backend = bytes; } public DefaultBases getCopy(){ return new DefaultBases(ArrayUtils.clone(backend)); } public int getLength(){ // or translated return backend.length; } public byte get(int n) { // or translated return backend[n]; } public char charAt(int n) { // or translated return (char) backend[n]; } public byte[] toByteArray() { // or translated return backend; } public byte[] toByteArray(int startIndexInclusive, int endIndexInclusive) { byte[] subArray = ArrayUtils.subarray(backend, startIndexInclusive, endIndexInclusive + 1); return subArray; } @Override public String toString() { String asString = null; // or translated try { asString = new String(backend, TEXT_FILE_BYTE_ENCODING); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return asString; } public void writeBasesBetween(int start, int end, Writer out) throws IOException { String outString = new String(toByteArray(start, end), TEXT_FILE_BYTE_ENCODING); out.write(outString); } public void set(int n, byte newBase) { assureSize(n); backend[n] = newBase; } private void assureSize(int n) { // logger.info("backend.length" + backend.length); // logger.info("n" + n); if(n >= backend.length){ resize(n + 1); } } private void resize(int n) { logger.info("resize=" + n); int additionalCount = n - backend.length; byte[] additional = new byte[additionalCount]; Arrays.fill(additional, SequenceUtils.GAP_SYMBOL); backend = ArrayUtils.addAll(backend, additional); logger.info("backend.length=" + backend.length); } // convenience public void append(byte[] newBytes) { // logger.info("backend.length" + backend.length); // logger.info("newBytes.length" + newBytes.length); backend = ArrayUtils.addAll(backend, newBytes); // logger.info("backend.length" + backend.length); } public void moveBaseLeft(int n) { set(n - 1, get(n)); } public void moveBaseRight(int n) { set(n + 1, get(n)); } public void insertAt(int n, byte[] newBytes) { assureSize(n - 1); // logger.info("newBytes.length" + newBytes.length); // logger.info("backend.length" + backend.length); byte[] newArray = ArrayUtilities.insertAt(backend, n, newBytes); // logger.info("newArray.length" + newArray.length); backend = newArray; } public void replace(int startReplaceIndex, int stopReplaceIndex, byte[] insertBases) { // or translated // translate start stop and insert int newLength = backend.length - (stopReplaceIndex + 1 - startReplaceIndex) + insertBases.length; // TODO could check if length is less - then just clear and insert byte[] newBases = new byte[newLength]; // copy first untouched part of sequence System.arraycopy(backend, 0, newBases, 0, startReplaceIndex); // copy insert bases System.arraycopy(insertBases, 0, newBases, startReplaceIndex, insertBases.length); // copy last untouched part of sequence - if there is one if(stopReplaceIndex < backend.length - 1){ System.arraycopy(backend, stopReplaceIndex + 1, newBases, startReplaceIndex + insertBases.length, backend.length - (stopReplaceIndex + 1)); } backend = newBases; } public void deleteAll(byte target) { // how many to delete so we can create a new array right size int count = 0; for(int n = 0; n < backend.length; n++){ if(backend[n] == target){ count ++; } } // copy all bytes not to delete into new array if(count > 0){ byte[] newBackend = new byte[backend.length - count]; int index = 0; for(byte next : backend){ if(next != target){ newBackend[index] = next; index ++; } } backend = newBackend; } } public void delete(int[] toDelete) { if(toDelete == null || toDelete.length == 0){ return; } Arrays.sort(toDelete); // translate toDelete int nOutOfBounds = 0; for(int n = 0; n < toDelete.length; n++){ if(toDelete[n] < 0 || toDelete[n] >= backend.length){ nOutOfBounds ++; } } // create new array size removed selected bases byte[] newBases = new byte[backend.length - toDelete.length + nOutOfBounds]; int newIndex = 0; int deleteCount = 0; int nextToDelete = toDelete[deleteCount]; for(int n = 0;n < backend.length ;n++){ if(n == nextToDelete){ // dont copy this one deleteCount ++; if(deleteCount < toDelete.length){ nextToDelete = toDelete[deleteCount]; }else{ nextToDelete = -1; } } else{ newBases[newIndex] = backend[n]; newIndex ++; } } backend = newBases; } // ????? public void complement() { NucleotideUtilities.complement(backend); } // ????? public void reverse() { ArrayUtils.reverse(backend); } // convenience method public void set(int n, char c) { set(n, (byte) c); } // convenience public void delete(int pos) { delete(new int[]{pos}); } // convenience public void insertAt(int n, byte newByte) { insertAt(n, new byte[]{newByte}); } }