    001    // Copyright 2007 by Basil Vandegriend.  All rights reserved.
    002    package com.basilv.envgen;
    003
    004    import java.io.BufferedReader;
    005    import java.io.IOException;
    006    import java.io.StringReader;
    007    import java.io.Writer;
    008    import java.util.Map;
    009
    010    import freemarker.template.TemplateModelException;
    011    import freemarker.template.TemplateTransformModel;
    012
    013    /**
    014     * Template to format input into a form acceptable for mainframes.
    015     * The formatting changes that are made are:
    016     * <ul>
    017     * <li>Convert tabs to spaces (4 spaces per tab)</li>
    018     * <li>Trim whitespace from end of line</li>
    019     * <li>Fail with error message if a line is longer than 75 characters</li>
    020     * </ul>
    021     */
    022    public class MainframeFileFormatTransform implements TemplateTransformModel {
    023
    024            static final int MAX_LINE_LENGTH = 75;
    025
    026            /**
    027             * Must have a default no-arg constructor.
    028             */
    029        public MainframeFileFormatTransform() {
    030        }
    031
    032
    033        public Writer getWriter(final Writer out, Map args) throws TemplateModelException {
    034
    035            // If you want to handle arguments to the transform, this is where it is done.
    036            // Any variables must be stored in the writer instance below and not in the main transform class.
    037
    038            final StringBuffer buffer = new StringBuffer();
    039                    return new Writer() {
    040                            public void write(char cbuf[], int off, int len) {
    041                                    buffer.append(cbuf, off, len);
    042                            }
    043
    044                            public void flush() throws IOException {
    045                                    out.flush();
    046                            }
    047
    048                            public void close() throws IOException {
    049                                    StringBuffer transformedBuffer = transform(buffer);
    050                                    out.write(transformedBuffer.toString());
    051                                    out.flush();
    052                            }
    053
    054                    };
    055        }
    056
    057        // Non-private for testing
    058            static StringBuffer transform(StringBuffer inputBuffer) throws IOException {
    059                    BufferedReader reader = new BufferedReader(new StringReader(inputBuffer.toString()));
    060                    StringBuffer outputBuffer = new StringBuffer(inputBuffer.length());
    061                    try {
    062                            int lineNumber = 0;
    063                            String line = reader.readLine();
    064                            while (line != null) {
    065                                    lineNumber++;
    066
    067                                    String transformedLine = transformLine(line, lineNumber);
    068                                    outputBuffer.append(transformedLine);
    069                                    outputBuffer.append("\n"); // since removed by readLine().
    070
    071                                    line = reader.readLine();
    072                            }
    073
    074                    } finally {
    075                            reader.close();
    076                    }
    077
    078                    return outputBuffer;
    079            }
    080
    081
    082            // Non-private for testing.
    083        static String transformLine(String line, int lineNumber) {
    084
    085                    if (line.length() == 0) {
    086                            return line;
    087                    }
    088
    089                    // Convert tabs to spaces
    090                    String newLine = line.replaceAll("\t", "    ");
    091
    092            // Trim ending whitespace
    093            int lastNonWhitespaceIndex = newLine.length() - 1;
    094            while (Character.isWhitespace(newLine.charAt(lastNonWhitespaceIndex))) {
    095                    lastNonWhitespaceIndex --;
    096                    if (lastNonWhitespaceIndex < 0) {
    097                            // Line is nothing but whitespace
    098                            return "";
    099                    }
    100            }
    101            newLine = newLine.substring(0, lastNonWhitespaceIndex+1);
    102
    103            if (newLine.length() > MAX_LINE_LENGTH) {
    104                    throw new RuntimeException("Line #" + lineNumber +
    105                                    " is longer than the maximum of " + MAX_LINE_LENGTH +
    106                                    " characters. Line content = [" + line + "].");
    107            }
    108
    109            return newLine;
    110        }
    111
    112    }