/* * Copyright 2005-2015 by BerryWorks Software, LLC. All rights reserved. * * This file is part of EDIReader. You may obtain a license for its use directly from * BerryWorks Software, and you may also choose to use this software under the terms of the * GPL version 3. Other products in the EDIReader software suite are available only by licensing * with BerryWorks. Only those files bearing the GPL statement below are available under the GPL. * * EDIReader is free software: you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * EDIReader is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with EDIReader. If not, * see <http://www.gnu.org/licenses/>. */ package com.berryworks.edireader.formatter; import com.berryworks.edireader.EDIReader; import com.berryworks.edireader.tokenizer.Tokenizer; import com.berryworks.edireader.util.sax.EDIReaderSAXAdapter; import org.xml.sax.Attributes; import java.io.IOException; import java.io.PrintWriter; import java.io.Reader; /** * A SAX Handler used within the Formatter utility program to receive the "XML" * elements parsed by EDIReader. */ public class FormatterHandler extends EDIReaderSAXAdapter { private final Reader input; protected final PrintWriter output; protected final EDIReader ediReader; protected String indent; private String filename; private int charsReadSoFar; public FormatterHandler(EDIReader reader, Reader input, PrintWriter output) { super(reader.getXMLTags()); this.ediReader = reader; this.input = input; this.output = output; } @Override protected void beginInterchange(int charCount, int segmentCharCount, Attributes attributes) { indent = ""; String segment = readSegment((charCount - segmentCharCount), segmentCharCount); output.println(indent + segment); } @Override protected void endInterchange(int charCount, int segmentCharCount) { indent = ""; String segment = readSegment((charCount - segmentCharCount), segmentCharCount); output.println(indent + segment); } @Override protected void beginExplicitGroup(int charCount, int segmentCharCount, Attributes attributes) { indent = " "; String segment = readSegment((charCount - segmentCharCount), segmentCharCount); output.println(indent + segment); } @Override protected void endExplicitGroup(int charCount, int segmentCharCount) { indent = " "; String segment = readSegment((charCount - segmentCharCount), segmentCharCount); output.println(indent + segment); } @Override protected void beginImplicitGroup() { indent = " "; endImplicitGroup(); } @Override protected void endImplicitGroup() { output.println(indent + "..."); } @Override protected void beginSegmentGroup(String loopName, Attributes atts) { output.println(indent + "+------ " + loopName); indent = indent + "| "; } @Override protected void beginAnotherSegment(Attributes atts) { super.beginAnotherSegment(atts); } @Override protected void beginFirstSegment(Attributes atts) { indent = indent + " "; } @Override protected void beginDocument(int charCount, int segmentCharCount, Attributes attributes) { indent = " "; String segment = readSegment((charCount - segmentCharCount), segmentCharCount); output.println(indent + segment); } @Override protected void endDocument(int charCount, int segmentCharCount) { // System.err.println("endDocument"); indent = " "; String segment = readSegment((charCount - segmentCharCount), segmentCharCount); output.println(indent + segment); } @Override protected void beginImplicitDocument() { // System.err.println("begin implicit document"); indent = " "; } @Override protected void endSegment(int charCount, int segmentCharCount) { String segment = readSegment((charCount - segmentCharCount), segmentCharCount); output.println(indent + segment); } @Override protected void endSegmentGroup() { indent = indent.substring(0, indent.length() - 3); output.println(indent + "+-----------"); } protected String readSegment(int offset, int length) { char[] buf; // First deal with skipping ahead if needed if (charsReadSoFar < offset) { int toSkip = offset - charsReadSoFar; while (toSkip > 0) { try { if (!input.ready()) Thread.yield(); long n = input.skip(toSkip); if (n > 0) { toSkip -= n; charsReadSoFar += n; } } catch (IOException e) { throw new RuntimeException( "Unexpected skip exception on duplicate pipe ", e); } } } if (charsReadSoFar == offset) { // normal case: no skipped chars buf = new char[length]; int n = 0; while (n < length) { try { if (!input.ready()) Thread.yield(); int i = input.read(buf, n, length - n); if (i == -1) break; else if (i < length - n) Thread.yield(); if (i > 0) { n += i; charsReadSoFar += i; } } catch (IOException e) { throw new RuntimeException( "Unexpected read exception on duplicate pipe ", e); } } } else { throw new RuntimeException("Unexpected attempt to skip backwards"); } // Determine the index of the last non-whitespace and non-control // char in the segment int i; for (i = buf.length; i > 0; i--) if ((Tokenizer.WHITESPACE.indexOf(buf[i - 1]) < 0) && (!Character.isISOControl(buf[i - 1]))) break; return new String(buf, 0, i); } @Override protected void recover(Exception e) { System.err.println("recovering from " + e.getMessage()); } public String getFilename() { return filename; } public void setFilename(String filename) { this.filename = filename; } @Override public int getSegmentCharCount() { int n = super.getSegmentCharCount(); return n == -1 ? ediReader.getSegmentCharCount() : n; } @Override public int getCharCount() { int n = super.getCharCount(); return n == -1 ? ediReader.getCharCount() : n; } public void start(String uri, String name, String data, Attributes attributes) { } public void end(String uri, String name) { } @Override public void preface() { } @Override public void addendum() { } }