Jun 102013
 

This class formats a string to line break at a specific character position. It can also limit the number of rows of
the string. There are probably already better ways of doing this, but this filled my needs and makes for a good future
reference for me.

 

package bolin;

import java.io.Serializable;
import java.util.Scanner;

/**
 * This class provides functionality for formatting a String to a specific number of characters
 * per row and a specific number of rows.
 * @author Steven Bolin
 */
public class MyMessageFormatter implements MessageFormatter, Serializable {

	private static final long serialVersionUID = 1L;
	private String unformattedMessage;
	private Integer maxLineLength;
	private String formattedMessage;
	private Integer maxLineCount;
	private boolean limitLineCount;

	/**
	 * Initializes the MessageFormatter with the message argument and the max line
	 * length of 65 characters.
	 * 
	 * @param message
	 *          The message to be formatted.
	 */
	public MyMessageFormatter (String message) {
		this.unformattedMessage = message;
		this.maxLineLength = 65;
		this.maxLineCount = 196;
		this.limitLineCount(false);
		this.formattedMessage = null;
	}

	/**
	 * Initializes the MessageFormatter to an empty state. Max line length 
	 * defaults to 65 characters.
	 */
	public MyMessageFormatter () {
		this.unformattedMessage = "";
		this.setMaxLineLength(65); // 65 is an arbitrary choice for default. 
		this.formattedMessage = null;
		this.setMaxLineCount(0);
		this.limitLineCount(false);
	}

	/**
	 * Formats message to where lines are no more than lineLength characters long
	 * and makes all characters upper case
	 * 
	 * @param message
	 * @return Returns formatted message where lines are no more than lineLength
	 *         characters long and makes all characters upper case
	 */
	private String formatMessage(String message) {
		// There is probably a lot of room for improvement to this method, but having
		// gotten it to work as desired.

		if (this.maxLineLength <= 0) {
			message = "";
		} else {
			Character c = null; 				// The character being inspected
			Integer messageLength = message.length();	// The length of the message being formatted
			String line = "";				// Essentially a character buffer used to build each line
			Integer lineLimit = this.maxLineLength + 1;	// The length of the line. One more than maxLineLength to
                                                                        // evaluate the char after maxLinelength
			String revisedMessage = "";			// Used to build the formatted message.

			// If the message is shorter than the maxLineLength, then just leave it alone.
			if (message.length() < this.maxLineLength) {
				revisedMessage = message;
			} else {

				// Otherwise, inspect each character looking for \n or \c and/or adding \n as required
				for (int i = 0; i < messageLength; i++) {

					c = message.charAt(i);
					line = line + c;

					// If the line already ends with a newline, then add it to the revised msg
					if (c.equals('\n') || c.equals('\r')) {
						revisedMessage = revisedMessage + line;
						line = "";

					} else {
						// otherwise, check if the buffer (line) is full and add the newline
						if (line.length() == lineLimit) {
							line = line.substring(0, this.maxLineLength) + '\n'; 	// Keep all but the last char and replace the last char with newline
							revisedMessage = revisedMessage + line;			// Add it to the revised msg
							line = "";	// Clear the buffer
							i--;	// Decrement i to re-inspect that last character.
						}
					}
				}
				revisedMessage = revisedMessage + line;		// Add the remaining content of the buffer to the revised msg
			}

			message = revisedMessage;    // Update message to the revised version
		}

		// If the number of lines to the message is to be limited, then do so now
		if (this.limitLineCount) {
			message = this.limitRows(message);
		}

		// Return the uppercase version of the revised message.
		return message.toUpperCase();
	}

	/**
	 * Limits the number of rows to the number set by this.maxLines. It will
	 * return a String with the message truncated at the maxLines number of rows.
	 * 
	 * @param message
	 *          The message to limit the number of rows for
	 * @return It will return a String with the message truncated at the maxLines
	 *         number of rows.
	 */
	private String limitRows(String message) {
		Scanner scanner = new Scanner(message);
		Integer count = 0;
		String result = "";

		if ((count < this.maxLineCount) && scanner.hasNextLine()) {
			result = result + scanner.nextLine();
			count++;
		}

		while ((count < this.maxLineCount) && scanner.hasNextLine()) { 			
                  result = result + "\n" + scanner.nextLine();
  		  count++; 		
                }
 		scanner.close();
 		return result;
 	}

 	@Override
 	public Integer getLineCount() {
 		Scanner scanner = new Scanner(this.formatMessage(unformattedMessage));
 		Integer count = 0;
 		while (scanner.hasNextLine()) {
 			count++;
 			scanner.nextLine();
 		}
 		scanner.close();

 		String message = this.formatMessage(unformattedMessage);
 		count = message.length() > 0 ? 1 : 0;
		for(int i=0; i< message.length(); i++) {
		  if(message.charAt(i) == '\n') {
		    count++;
		  }
		}

		return count;
	}

	@Override
	public void setUnformattedMessage(String message) {
		this.unformattedMessage = message;
	}

	@Override
	public Integer getMaxLineLength() {
		return maxLineLength;
	}

	@Override
	public void setMaxLineLength(Integer lineLength) {
		this.maxLineLength = (lineLength < 0) ? 0 : lineLength;
	}

	@Override
	public String getFormattedMessage() {
		this.formattedMessage = this.formatMessage(unformattedMessage);
		return formattedMessage;
	}

	@Override
	public Integer characterCount() {
		return this.formatMessage(unformattedMessage).length();
	}

	@Override
	public Integer getMaxLineCount() {
		return maxLineCount;
	}

	@Override
	public void setMaxLineCount(Integer maxLineCount) {
		this.maxLineCount = maxLineCount;
	}

	@Override
	public void limitLineCount(boolean limitLineCount) {
		this.limitLineCount = limitLineCount;
	}

	@Override
	public void setLimitLineCount(boolean limitLineCount) {
		this.limitLineCount = limitLineCount;
	}

} // End of class
 Posted by at 4:22 pm