//CipherStreamJava/src/main/java/com/mattrixwv/CipherStreamJava/monoSubstitution/Caesar.java //Matthew Ellison // Created: 07-25-21 //Modified: 04-16-23 package com.mattrixwv.cipherstream.monosubstitution; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.mattrixwv.cipherstream.exceptions.InvalidInputException; public class Caesar{ protected static Logger logger = LoggerFactory.getLogger(Caesar.class); //Fields protected String inputString; //The string that needs encoded/decoded protected String outputString; //The encoded/decoded string protected int shift; //The amount that you need to shift each letter protected boolean preserveCapitals; //Whether to respect capitals in the output string protected boolean preserveWhitespace; //Whether to respect whitespace in the output string protected boolean preserveSymbols; //Whether to respect symbols in the output string //Sets shift and makes sure it is within the propper bounds protected void setShift(int shiftAmount){ logger.debug("Setting shift {}", shiftAmount); //If you shift more than 26 you will just be wrapping back around again shift = shiftAmount % 26; logger.debug("Cleaned shift {}", shift); } //Sets the input string protected void setInputString(String inputString) throws InvalidInputException{ if(inputString == null){ throw new InvalidInputException("Input cannot be null"); } logger.debug("Original input string '{}'", inputString); if(!preserveCapitals){ logger.debug("Removing case"); inputString = inputString.toLowerCase(); } if(!preserveWhitespace){ logger.debug("Removing whitespace"); inputString = inputString.replaceAll("\\s", ""); } if(!preserveSymbols){ logger.debug("Removing symbols"); inputString = inputString.replaceAll("[^a-zA-Z\\s]", ""); } logger.debug("Cleaned input string '{}'", inputString); this.inputString = inputString; if(this.inputString.isBlank()){ throw new InvalidInputException("Input must contain at least 1 letter"); } } //Encodes the inputString and stores the result in outputString protected String encode(){ logger.debug("Encoding"); StringBuilder output = new StringBuilder(); for(int cnt = 0;cnt < inputString.length();++cnt){ char currentChar = inputString.charAt(cnt); //A temperary holder for the current working character logger.debug("Working character {}", currentChar); //If it is an upper case letter shift it and wrap if necessary if(Character.isUpperCase(currentChar)){ logger.debug("Encoding uppercase"); currentChar += shift; //Wrap around if the letter is now out of bounds if(currentChar < 'A'){ logger.debug("Wrapping around to Z"); currentChar += 26; } else if(currentChar > 'Z'){ logger.debug("Wrapping around to A"); currentChar -= 26; } } //If it is a lower case letter shift it and wrap if necessary else if(Character.isLowerCase(currentChar)){ logger.debug("Encoding lowercase"); currentChar += shift; //Wrap around if the letter is now out of bounds if(currentChar < 'a'){ logger.debug("Wrapping around to z"); currentChar += 26; } else if(currentChar > 'z'){ logger.debug("Wrapping around to a"); currentChar -= 26; } } //If it is whitespace, number, or punctuation just let it pass through //Add it to the output string logger.debug("Encoded character {}", currentChar); output.append(currentChar); } outputString = output.toString(); logger.debug("Saving encoded string '{}'", outputString); return outputString; } //Decodes the inputString and stores the result in outputString protected String decode(){ logger.debug("Decoding"); StringBuilder output = new StringBuilder(); for(int cnt = 0;cnt < inputString.length();++cnt){ char currentChar = inputString.charAt(cnt); //A temperary holder for the current working character logger.debug("Working character {}", currentChar); //If it is an upper case letter shift it and wrap if necessary if(Character.isUpperCase(currentChar)){ logger.debug("Decoding uppercase"); currentChar -= shift; //Wrap around if the letter is now out of bounds if(currentChar < 'A'){ logger.debug("Wrapping around to Z"); currentChar += 26; } else if(currentChar > 'Z'){ logger.debug("Wrapping around to A"); currentChar -= 26; } } //If it is a lower case letter shift it and wrap if necessary else if(Character.isLowerCase(currentChar)){ logger.debug("Decoding lowercase"); currentChar -= shift; //Wrap around if the letter is now out of bounds if(currentChar < 'a'){ logger.debug("Wrapping around to z"); currentChar += 26; } else if(currentChar > 'z'){ logger.debug("Wrapping around to a"); currentChar -= 26; } } //If it is whitespace, number, or punctuation just let it pass through //Add it to the output string logger.debug("Decoded character {}", currentChar); output.append(currentChar); } outputString = output.toString(); logger.debug("Saving decoded string '{}'", outputString); return outputString; } //Constructor public Caesar(){ reset(); preserveCapitals = false; preserveWhitespace = false; preserveSymbols = false; } public Caesar(boolean preserveCapitals, boolean preserveWhitespace, boolean preserveSymbols){ reset(); this.preserveCapitals = preserveCapitals; this.preserveWhitespace = preserveWhitespace; this.preserveSymbols = preserveSymbols; } //Sets the shift and inputString and encodes the message public String encode(int shiftAmount, String inputString) throws InvalidInputException{ reset(); setShift(shiftAmount); setInputString(inputString); return encode(); } //Sets the shift and inputString and decodes the message public String decode(int shiftAmount, String inputString) throws InvalidInputException{ reset(); setShift(shiftAmount); setInputString(inputString); return decode(); } //Returns the inputString public String getInputString(){ return inputString; } //Returns shift public int getShift(){ return shift; } //Returns the outputString public String getOutputString(){ return outputString; } //Makes sure all of the variables are empty public void reset(){ logger.debug("Resetting fields"); inputString = ""; outputString = ""; shift = 0; } }