All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.codetaco.funnel.publisher.VariableLengthPublisher Maven / Gradle / Ivy

There is a newer version: 3.0.5
Show newest version
package com.codetaco.funnel.publisher;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.ParseException;
import java.util.Formatter;

import com.codetaco.funnel.orderby.KeyPart;
import com.codetaco.funnel.parameters.FunnelContext;
import com.codetaco.funnel.parameters.HexDump;
import com.codetaco.funnel.segment.SourceProxyRecord;

/**
 * 

* Abstract VariableLengthPublisher class. *

* * @author Chris DeGreef [email protected] */ abstract public class VariableLengthPublisher extends AbstractPublisher { private static final byte[] HEX_CHARS = new byte[16]; static { byte b; int i = 0; for (b = '0'; b <= '9'; b++) HEX_CHARS[i++] = b; for (b = 'A'; b <= 'F'; b++) HEX_CHARS[i++] = b; } private static int appendDecChars(final int i, final byte[] chars, final int startOffset) { int offset; int value; offset = startOffset; value = i; StringBuilder sb; try (final Formatter fmt = new Formatter(sb = new StringBuilder())) { fmt.format("%04d", value); } final byte[] ba = sb.toString().getBytes(); int bao = 0; // chars[offset++] = ba[bao++]; // chars[offset++] = ba[bao++]; // chars[offset++] = ba[bao++]; // chars[offset++] = ba[bao++]; chars[offset++] = ba[bao++]; chars[offset++] = ba[bao++]; chars[offset++] = ba[bao++]; chars[offset++] = ba[bao++]; return offset; } private static int appendHexChars(final byte b, final byte[] chars, final int startOffset) { int byteAsInt, offset; byteAsInt = b; offset = startOffset; chars[offset++] = HEX_CHARS[byteAsInt >> 4 & 0x0F]; chars[offset++] = HEX_CHARS[byteAsInt & 0x0F]; return offset; } private static final int dumpBuffSize(final int p_charsPerRow) { return (13 + (p_charsPerRow * 2) + (p_charsPerRow / 4) + p_charsPerRow); } /** *

* Constructor for VariableLengthPublisher. *

* * @param _context a {@link com.codetaco.funnel.parameters.FunnelContext} * object. * @throws java.text.ParseException if any. * @throws java.io.IOException if any. */ public VariableLengthPublisher(final FunnelContext _context) throws ParseException, IOException { super(_context); originalBytes = new byte[1024]; } /** * @param item * @param rawData * @throws IOException */ void formatHexDumpAndWrite(final SourceProxyRecord item, final byte[] rawData) throws IOException, Exception { StringWriter sw; PrintWriter pw; String line; pw = new PrintWriter(sw = new StringWriter()); pw.printf("# %d @ %d for %d", item.getOriginalRecordNumber(), item.originalLocation, item.originalSize); line = sw.toString(); write(line.getBytes(), 0, line.length()); newLine(); for (final HexDump dumpee : context.getHexDumps()) { final KeyPart column = context.columnHelper.get(dumpee.columnName); if (column != null) { /* * field header */ pw = new PrintWriter(sw = new StringWriter()); pw.printf("%s", dumpee.columnName); line = sw.toString(); write(line.getBytes(), 0, line.length()); newLine(); } if (column != null) hexDump(column.getContentsAsByteArray(), column.offset); else hexDump(rawData, 0, item.originalSize); } /* * record separator */ newLine(); } @Override void formatOutputAndWrite(final SourceProxyRecord item, final byte[] rawData) throws IOException, Exception { if (context.getHexDumps() == null || context.getFormatOutDefs() != null) { /* * The --format can be empty, causing the entire row to be written, * unless a --hexdump is requested. In that case we would not write * the row. */ context.formatOutHelper.format(this, rawData, item.originalSize, item, true); newLine(); } super.formatOutputAndWrite(item, rawData); if (context.getHexDumps() != null) formatHexDumpAndWrite(item, rawData); } private void hexDump(final byte[] bytesToDump, final int fieldOffsetInRow) throws IOException { hexDump(bytesToDump, fieldOffsetInRow, bytesToDump.length); } private void hexDump(final byte[] bytesToDump, final int fieldOffsetInRow, final int length) throws IOException { hexDump(bytesToDump, fieldOffsetInRow, length, 16, new byte[dumpBuffSize(16)]); } private void hexDump(final byte[] p_array, final int p_startPrintedOffset, final int p_numBytes, final int p_charsPerRow, final byte[] byteBuffer) throws IOException { byte asciiByteValue; int offset, i, relOffset, endOffset, outLen, printedOffset; /* * Compute endOffset and adjust if it would cause us to index out of * bounds. endOffset is 1 more than the last p_array cell we will * reference. */ endOffset = p_numBytes; if (endOffset > p_array.length) endOffset = p_array.length; printedOffset = p_startPrintedOffset; offset = 0; while (offset < endOffset) { // Append the offset as a hex number and 1 of the 2 spaces that // follow it. outLen = 0; outLen = appendDecChars(printedOffset, byteBuffer, outLen); byteBuffer[outLen++] = ' '; // Now build the hex representation. // On the 0th, 4th, 8th, , etc. element we'll pre-pend a blank // If the relOffset is >= endOffset, we put in 2 blanks, not hex // digits. for (i = 0; i < p_charsPerRow; i++) { relOffset = offset + i; if ((i & 0x03) == 0) byteBuffer[outLen++] = ' '; if (relOffset < endOffset) outLen = appendHexChars(p_array[relOffset], byteBuffer, outLen); else { byteBuffer[outLen++] = ' '; byteBuffer[outLen++] = ' '; } } /* * Now append 2 spaces and the "| delimiter; we'll format the ASCII * portion now. */ byteBuffer[outLen++] = ' '; byteBuffer[outLen++] = ' '; byteBuffer[outLen++] = '|'; for (i = 0; i < p_charsPerRow; i++) { relOffset = offset + i; if (relOffset < endOffset) { asciiByteValue = p_array[relOffset]; if (asciiByteValue < ' ' || asciiByteValue > '~') asciiByteValue = '.'; } else asciiByteValue = ' '; byteBuffer[outLen++] = asciiByteValue; } /* * Add on final "|" at the end, print to print stream, and increment * offset by charsPerRow. */ byteBuffer[outLen++] = '|'; write(byteBuffer, 0, outLen); newLine(); offset += p_charsPerRow; printedOffset += p_charsPerRow; } } @Override void loadOriginalBytes(final int originalFileNumber, final SourceProxyRecord item) throws IOException { if (item.originalSize > originalBytes.length) originalBytes = new byte[item.originalSize + 1024]; /* * Make sure to delimit the current record length in the input buffer. */ originalBytes[item.originalSize] = 0x00; super.loadOriginalBytes(originalFileNumber, item); } @Override void newLine() throws IOException { write(context.getEndOfRecordDelimiterOut(), 0, context.getEndOfRecordDelimiterOut().length); } @Override void publishHeader() throws IOException { super.publishHeader(); /* * This is the first time publishing to this file. So lets see if there * is a header tucked away in the csv context area. We will write that * out first. */ if (context.getCsv() != null && context.getCsv().header && context.getCsv().headerContents != null) { write(context.getCsv().headerContents, 0, context.getCsv().headerContents.length); newLine(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy