@Override
    public void parse(InputStream stream, ContentHandler handler, Metadata metadata,
                      ParseContext context) throws IOException, SAXException, TikaException {
        metadata.set(Metadata.CONTENT_TYPE, TYPE_SAS7BDAT.toString());

        XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
        xhtml.startDocument();

        SasFileReader sas = new SasFileReaderImpl(stream);
        SasFileProperties props = sas.getSasFileProperties();

        // Record the interesting parts of the file's metadata
        metadata.set(TikaCoreProperties.TITLE, props.getName());
        metadata.set(TikaCoreProperties.CREATED, props.getDateCreated());
        metadata.set(TikaCoreProperties.MODIFIED, props.getDateModified());

        metadata.set(PagedText.N_PAGES, (int) props.getPageCount());
        metadata.set(Database.COLUMN_COUNT, (int) props.getColumnsCount());
        metadata.set(Database.ROW_COUNT, (int) props.getRowCount());

        // TODO Can we find more general properties for these / move
        //  these to more general places?
        metadata.set(HttpHeaders.CONTENT_ENCODING, props.getEncoding());
        metadata.set(OfficeOpenXMLExtended.APPLICATION, props.getServerType());
        metadata.set(OfficeOpenXMLExtended.APP_VERSION, props.getSasRelease());
        metadata.set(MachineMetadata.ARCHITECTURE_BITS, props.isU64() ? "64" : "32");
        metadata.set(MachineMetadata.ENDIAN,
                props.getEndianness() == 1 ? MachineMetadata.Endian.LITTLE.getName() :
                        MachineMetadata.Endian.BIG.getName());

        // The following SAS Metadata fields are currently ignored:
        // compressionMethod
        // sessionEncoding
        // fileType
        // osName - 
        // osType - 
        // mixPageRowCount
        // headerLength
        // pageLength
        // rowLength

        // Process the column metadata
        // TODO Find keys to record the format and the type
        for (Column c : sas.getColumns()) {
            String name = c.getLabel();
            if (name == null || name.isEmpty()) {
                name = c.getName();
            }
            metadata.add(Database.COLUMN_NAME, name);
        }


        // Output file contents as a table
        xhtml.element("h1", props.getName());
        xhtml.startElement("table");
        xhtml.newline();

        // Do the column headings
        xhtml.startElement("tr");
        for (Column c : sas.getColumns()) {
            String label = c.getLabel();
            if (label == null || label.isEmpty()) {
                label = c.getName();
            }

            xhtml.startElement("th", "title", c.getName());
            xhtml.characters(label);
            xhtml.endElement("th");
        }
        xhtml.endElement("tr");
        xhtml.newline();

        //TODO: initialize this on the first row and then apply
        Map<Integer, Format> formatMap = new HashMap<>();

        // Process each row in turn
        Object[] row = null;
        while ((row = sas.readNext()) != null) {
            xhtml.startElement("tr");
            for (String val : DataWriterUtil.getRowValues(sas.getColumns(), row, formatMap)) {
                // Use explicit start/end, rather than element, to 
                //  ensure that empty cells still get output
                xhtml.startElement("td");
                xhtml.characters(val);
                xhtml.endElement("td");
            }
            xhtml.endElement("tr");
            xhtml.newline();
        }

        // Finish
        xhtml.endElement("table");
        xhtml.endDocument();
    }
@Test
    public void testSimpleFile() throws Exception {
        ContentHandler handler = new BodyContentHandler();
        Metadata metadata = new Metadata();

        try (InputStream stream = getResourceAsStream("/test-documents/testSAS.sas7bdat")) {
            parser.parse(stream, handler, metadata, new ParseContext());
        }

        assertEquals("application/x-sas-data", metadata.get(Metadata.CONTENT_TYPE));
        assertEquals("TESTING", metadata.get(TikaCoreProperties.TITLE));

        // Mon Jan 30 07:31:47 GMT 2017
        assertEquals("2017-01-30T07:31:47Z", metadata.get(TikaCoreProperties.CREATED));
        assertEquals("2017-01-30T07:31:47Z", metadata.get(TikaCoreProperties.MODIFIED));

        assertEquals("1", metadata.get(PagedText.N_PAGES));
        assertEquals("2", metadata.get(Database.COLUMN_COUNT));
        assertEquals("11", metadata.get(Database.ROW_COUNT));
        assertEquals("windows-1252", metadata.get(HttpHeaders.CONTENT_ENCODING));
        assertEquals("W32_7PRO", metadata.get(OfficeOpenXMLExtended.APPLICATION));
        assertEquals("9.0301M2", metadata.get(OfficeOpenXMLExtended.APP_VERSION));
        assertEquals("32", metadata.get(MachineMetadata.ARCHITECTURE_BITS));
        assertEquals("Little", metadata.get(MachineMetadata.ENDIAN));
        assertEquals(Arrays.asList("recnum", "label"),
                Arrays.asList(metadata.getValues(Database.COLUMN_NAME)));

        String content = handler.toString();
        assertContains("TESTING", content);
        assertContains("\t3\t", content);
        assertContains("\t10\t", content);
        assertContains("\tThis is row", content);
        assertContains(" of ", content);
    }