001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.nbio.survival.data;
022
023import java.io.*;
024import java.util.*;
025
026/**
027 * Need to handle very large spreadsheets of expression data so keep memory
028 * footprint low
029 *
030 * @author Scooter Willis <willishf at gmail dot com>
031 */
032public class WorkSheet {
033
034        private LinkedHashMap<String, HeaderInfo> columnLookup = new LinkedHashMap<String, HeaderInfo>();
035        private LinkedHashMap<String, HeaderInfo> rowLookup = new LinkedHashMap<String, HeaderInfo>();
036        private CompactCharSequence[][] data = new CompactCharSequence[1][1];
037        HashMap<String, String> dataGrid = new HashMap<String, String>();
038        private String indexColumnName = "";
039
040        /**
041         *
042         */
043        public WorkSheet() {
044        }
045
046        /**
047         *
048         * @param rows
049         * @param columns
050         * @throws Exception
051         */
052        public WorkSheet(Collection<String> rows, Collection<String> columns) throws Exception {
053                //    rowsList = new ArrayList<String>(rows);
054                int i = 1;
055                for (String row : rows) {
056                        if (rowLookup.containsKey(row)) {
057                                throw new Exception("Duplicate row " + row);
058                        }
059                        rowLookup.put(row, new HeaderInfo(i));
060                        i++;
061                }
062                i = 1;
063                for (String col : columns) {
064                        if (columnLookup.containsKey(col)) {
065                                throw new Exception("Duplicate row " + col);
066                        }
067                        columnLookup.put(col, new HeaderInfo(i));
068                        i++;
069                }
070
071
072
073                //  columnsList.trimToSize();
074                //  rowsList.trimToSize();
075                data = new CompactCharSequence[rowLookup.size() + 1][columnLookup.size() + 1];
076        }
077
078        /**
079         *
080         * @param values
081         */
082        public WorkSheet(String[][] values) {
083                //    System.out.println("In worksheet init " + Runtime.getRuntime().totalMemory());
084                String[] columns = new String[values[0].length];
085                for (int i = 0; i < columns.length; i++) {
086                        columns[i] = new String(values[0][i].getBytes());
087                }
088                for (int i = 1; i < columns.length; i++) {
089                        columnLookup.put(columns[i], new HeaderInfo(i));
090                }
091
092
093                for (int i = 1; i < values.length; i++) {
094                        String row = new String(values[i][0].getBytes());
095                        rowLookup.put(row, new HeaderInfo(i));
096                }
097
098                data = new CompactCharSequence[values.length][values[0].length];
099                for (int row = 0; row < values.length; row++) {
100                        for (int col = 0; col < values[0].length; col++) {
101                                String value = values[row][col];
102                                data[row][col] = new CompactCharSequence(value);
103                                values[row][col] = null;
104                        }
105                        System.out.println("Row " + row + " " + Runtime.getRuntime().totalMemory());
106
107                }
108                values = null;
109                System.gc();
110                //data = values;
111
112        }
113
114        /**
115         * See if we can free up memory
116         */
117        public void clear() {
118                columnLookup.clear();
119                rowLookup.clear();
120                data = null;
121                dataGrid.clear();
122                doubleValues.clear();
123                System.gc();
124        }
125
126        @Override
127        public String toString() {
128                return super.toString(); //To change body of generated methods, choose Tools | Templates.
129        }
130
131        /**
132         * Split a worksheet randomly. Used for creating a discovery/validation data
133         * set The first file name will matched the percentage and the second file
134         * the remainder
135         *
136         * @param percentage
137         * @param fileName1
138         * @param fileName2
139         * @throws Exception
140         */
141        public void randomlyDivideSave(double percentage, String fileName1, String fileName2) throws Exception {
142                ArrayList<String> rows = this.getDataRows();
143                Collections.shuffle(rows);
144                int portion = (int) (rows.size() * percentage);
145                for (int i = 0; i < portion; i++) {
146                        this.hideRow(rows.get(i), true);
147                }
148                this.saveTXT(fileName2);
149                for (int i = 0; i < portion; i++) {
150                        this.hideRow(rows.get(i), false);
151                }
152                for (int i = portion; i < rows.size(); i++) {
153                        this.hideRow(rows.get(i), true);
154                }
155                this.saveTXT(fileName1);
156                for (int i = portion; i < rows.size(); i++) {
157                        this.hideRow(rows.get(i), false);
158                }
159
160        }
161
162        /**
163         * Create a copy of a worksheet. If shuffling of columns or row for testing
164         * a way to duplicate original worksheet
165         *
166         * @param copyWorkSheet
167         * @param rows
168         * @return
169         * @throws Exception
170         */
171        static public WorkSheet getCopyWorkSheetSelectedRows(WorkSheet copyWorkSheet, ArrayList<String> rows) throws Exception {
172
173                ArrayList<String> columns = copyWorkSheet.getColumns();
174
175
176                WorkSheet workSheet = new WorkSheet(rows, columns);
177                for (String row : rows) {
178                        for (String col : columns) {
179                                workSheet.addCell(row, col, copyWorkSheet.getCell(row, col));
180                        }
181                }
182                workSheet.setMetaDataColumns(copyWorkSheet.getMetaDataColumns());
183                workSheet.setMetaDataRows(copyWorkSheet.getMetaDataRows());
184                return workSheet;
185
186        }
187
188        /**
189         * Create a copy of a worksheet. If shuffling of columns or row for testing
190         * a way to duplicate original worksheet
191         *
192         * @param copyWorkSheet
193         * @return
194         * @throws Exception
195         */
196        static public WorkSheet getCopyWorkSheet(WorkSheet copyWorkSheet) throws Exception {
197                ArrayList<String> rows = copyWorkSheet.getRows();
198                ArrayList<String> columns = copyWorkSheet.getColumns();
199
200
201                WorkSheet workSheet = new WorkSheet(rows, columns);
202                for (String row : rows) {
203                        for (String col : columns) {
204                                workSheet.addCell(row, col, copyWorkSheet.getCell(row, col));
205                        }
206                }
207                workSheet.setMetaDataColumns(copyWorkSheet.getMetaDataColumns());
208                workSheet.setMetaDataRows(copyWorkSheet.getMetaDataRows());
209                return workSheet;
210
211        }
212
213        /**
214         *
215         * @param values
216         */
217        public WorkSheet(CompactCharSequence[][] values) {
218                //     System.out.println("In worksheet init " + Runtime.getRuntime().totalMemory());
219                String[] columns = new String[values[0].length];
220                for (int i = 0; i < columns.length; i++) {
221                        columns[i] = values[0][i].toString();
222                }
223                this.setIndexColumnName(columns[0]);
224                for (int i = 1; i < columns.length; i++) {
225                        columnLookup.put(columns[i], new HeaderInfo(i));
226                }
227
228
229                for (int i = 1; i < values.length; i++) {
230                        String row = values[i][0].toString();
231                        rowLookup.put(row, new HeaderInfo(i));
232                }
233
234                data = values;
235        }
236        private LinkedHashMap<String, String> metaDataColumnsHashMap = new LinkedHashMap<String, String>();
237
238        /**
239         *
240         * @return
241         */
242        public ArrayList<String> getMetaDataColumns() {
243                ArrayList<String> metaColumns = new ArrayList<String>();
244                for (String key : metaDataColumnsHashMap.keySet()) {
245                        HeaderInfo hi = columnLookup.get(key);
246                        if (!hi.isHide()) {
247                                metaColumns.add(key);
248                        }
249                }
250                return metaColumns;
251        }
252
253        /**
254         *
255         * @return
256         */
257        public ArrayList<String> getMetaDataRows() {
258                ArrayList<String> metaRows = new ArrayList<String>();
259                for (String key : metaDataRowsHashMap.keySet()) {
260                        HeaderInfo hi = rowLookup.get(key);
261                        if (!hi.isHide()) {
262                                metaRows.add(key);
263                        }
264                }
265                return metaRows;
266        }
267
268        /**
269         *
270         * @return
271         */
272        public ArrayList<String> getDataColumns() {
273                ArrayList<String> dataColumns = new ArrayList<String>();
274                ArrayList<String> columns = this.getColumns();
275                for (String column : columns) {
276                        if (!metaDataColumnsHashMap.containsKey(column)) {
277                                dataColumns.add(column);
278                        }
279                }
280                return dataColumns;
281        }
282
283        /**
284         * Randomly shuffle the columns and rows. Should be constrained to the same
285         * data type if not probably doesn't make any sense.
286         *
287         * @param columns
288         * @param rows
289         * @throws Exception
290         */
291        public void shuffleColumnsAndThenRows(ArrayList<String> columns, ArrayList<String> rows) throws Exception {
292                doubleValues.clear();
293
294                for (String column : columns) { //shuffle all values in the column
295                        ArrayList<Integer> rowIndex = new ArrayList<Integer>();
296                        for (int i = 0; i < rows.size(); i++) {
297                                rowIndex.add(i);
298                        }
299                        Collections.shuffle(rowIndex);
300                        for (int i = 0; i < rows.size(); i++) {
301                                String row = rows.get(i);
302                                int randomIndex = rowIndex.get(i);
303                                String destinationRow = rows.get(randomIndex);
304
305
306                                String temp = this.getCell(destinationRow, column);
307                                String value = this.getCell(row, column);
308                                this.addCell(destinationRow, column, value);
309                                this.addCell(row, column, temp);
310                        }
311                }
312
313                for (String row : rows) {
314                        ArrayList<Integer> columnIndex = new ArrayList<Integer>();
315                        for (int i = 0; i < columns.size(); i++) {
316                                columnIndex.add(i);
317                        }
318                        Collections.shuffle(columnIndex);
319                        for (int i = 0; i < columns.size(); i++) {
320                                String column = columns.get(i);
321
322                                int randomIndex = columnIndex.get(i);
323                                String destinationCol = columns.get(randomIndex);
324
325
326                                String temp = this.getCell(row, destinationCol);
327                                String value = this.getCell(row, column);
328                                this.addCell(row, destinationCol, value);
329                                this.addCell(row, column, temp);
330                        }
331                }
332
333
334        }
335
336        /**
337         * Need to shuffle column values to allow for randomized testing. The
338         * columns in the list will be shuffled together
339         *
340         * @param columns
341         * @throws Exception
342         */
343        public void shuffleColumnValues(ArrayList<String> columns) throws Exception {
344                doubleValues.clear();
345                ArrayList<String> rows = this.getDataRows();
346                for (String column : columns) { //shuffle all values in the column
347                        ArrayList<Integer> rowIndex = new ArrayList<Integer>();
348                        for (int i = 0; i < rows.size(); i++) {
349                                rowIndex.add(i);
350                        }
351                        Collections.shuffle(rowIndex);
352                        for (int i = 0; i < rows.size(); i++) {
353                                String row = rows.get(i);
354                                int randomIndex = rowIndex.get(i);
355                                String destinationRow = rows.get(randomIndex);
356
357
358                                String temp = this.getCell(destinationRow, column);
359                                String value = this.getCell(row, column);
360                                this.addCell(destinationRow, column, value);
361                                this.addCell(row, column, temp);
362                        }
363                }
364
365        }
366
367        /**
368         * Need to shuffle rows values to allow for randomized testing. The rows in
369         * the list will be shuffled together
370         *
371         * @param rows
372         * @throws Exception
373         */
374        public void shuffleRowValues(ArrayList<String> rows) throws Exception {
375                doubleValues.clear();
376                ArrayList<String> columns = this.getColumns();
377                for (String row : rows) {
378                        ArrayList<Integer> columnIndex = new ArrayList<Integer>();
379                        for (int i = 0; i < columns.size(); i++) {
380                                columnIndex.add(i);
381                        }
382                        Collections.shuffle(columnIndex);
383
384                        for (int i = 0; i < columns.size(); i++) {
385                                String column = columns.get(i);
386                                int randomIndex = columnIndex.get(i);
387                                String destinationCol = columns.get(randomIndex);
388
389                                String temp = this.getCell(row, destinationCol);
390                                String value = this.getCell(row, column);
391                                this.addCell(row, destinationCol, value);
392                                this.addCell(row, column, temp);
393                        }
394                }
395
396        }
397
398        /**
399         *
400         * @param value
401         */
402        public void hideMetaDataColumns(boolean value) {
403                ArrayList<String> metadataColumns = this.getMetaDataColumns();
404                for (String column : metadataColumns) {
405                        this.hideColumn(column, value);
406                }
407        }
408
409        /**
410         *
411         * @param value
412         */
413        public void hideMetaDataRows(boolean value) {
414                ArrayList<String> metadataRows = this.getMetaDataRows();
415                for (String row : metadataRows) {
416                        this.hideRow(row, value);
417                }
418        }
419
420        /**
421         *
422         */
423        public void setMetaDataRowsAfterRow() {
424                this.setMetaDataRowsAfterRow("META_DATA");
425        }
426
427        /**
428         *
429         */
430        public void setMetaDataColumnsAfterColumn() {
431                this.setMetaDataColumnsAfterColumn("META_DATA");
432        }
433
434        /**
435         *
436         * @param row
437         */
438        public void setMetaDataRowsAfterRow(String row) {
439                ArrayList<String> rows = this.getRows();
440                boolean metarow = false;
441                for (String r : rows) {
442                        if (r.equals(row) && !metarow) {
443                                metarow = true;
444                        }
445                        if (metarow) {
446                                this.markMetaDataRow(r);
447                        }
448                }
449        }
450
451        /**
452         *
453         * @param column
454         */
455        public void setMetaDataColumnsAfterColumn(String column) {
456                ArrayList<String> cols = this.getColumns();
457                boolean metacolumns = false;
458                for (String col : cols) {
459                        if (col.equals(column) && !metacolumns) {
460                                metacolumns = true;
461                        }
462                        if (metacolumns) {
463                                this.markMetaDataColumn(col);
464                        }
465                }
466
467
468        }
469
470        /**
471         * Clears existing meta data columns and sets new ones
472         *
473         * @param metaDataColumns
474         */
475        public void setMetaDataColumns(ArrayList<String> metaDataColumns) {
476                metaDataColumnsHashMap.clear();
477                markMetaDataColumns(metaDataColumns);
478        }
479
480        /**
481         * marks columns as containing meta data
482         *
483         * @param metaDataColumns
484         */
485        public void markMetaDataColumns(ArrayList<String> metaDataColumns) {
486                for (String column : metaDataColumns) {
487                        metaDataColumnsHashMap.put(column, column);
488                }
489        }
490
491        /**
492         *
493         * @param column
494         */
495        public void markMetaDataColumn(String column) {
496                metaDataColumnsHashMap.put(column, column);
497        }
498
499        /**
500         *
501         * @param column
502         * @return
503         */
504        public boolean isMetaDataColumn(String column) {
505                if (metaDataColumnsHashMap.get(column) == null) {
506                        return false;
507                } else {
508                        return true;
509                }
510        }
511
512        /**
513         *
514         * @param row
515         * @return
516         */
517        public boolean isMetaDataRow(String row) {
518                if (metaDataRowsHashMap.get(row) == null) {
519                        return false;
520                } else {
521                        return true;
522                }
523        }
524        private LinkedHashMap<String, String> metaDataRowsHashMap = new LinkedHashMap<String, String>();
525
526        /**
527         *
528         * @param row
529         */
530        public void markMetaDataRow(String row) {
531                metaDataRowsHashMap.put(row, row);
532        }
533
534        /**
535         *
536         * @param metaDataRows
537         */
538        public void setMetaDataRows(ArrayList<String> metaDataRows) {
539                metaDataRowsHashMap.clear();
540                for (String row : metaDataRows) {
541                        metaDataRowsHashMap.put(row, row);
542                }
543        }
544
545        /**
546         *
547         * @throws Exception
548         */
549        public void hideEmptyRows() throws Exception {
550                ArrayList<String> rows = this.getDataRows();
551                ArrayList<String> columns = this.getDataColumns();
552                for (String row : rows) {
553                        boolean emptyRow = true;
554                        for (String column : columns) {
555                                String value = this.getCell(row, column).trim();
556                                if (value.length() > 0) {
557                                        emptyRow = false;
558                                        break;
559                                }
560                        }
561                        if (emptyRow) {
562                                hideRow(row, true);
563                        }
564                }
565
566        }
567
568        /**
569         *
570         * @throws Exception
571         */
572        public void hideEmptyColumns() throws Exception {
573                ArrayList<String> rows = this.getDataRows();
574                ArrayList<String> columns = this.getDataColumns();
575                for (String column : columns) {
576                        boolean emptyColumn = true;
577                        for (String row : rows) {
578                                String value = this.getCell(row, column).trim();
579                                if (value.length() > 0) {
580                                        emptyColumn = false;
581                                        break;
582                                }
583                        }
584                        if (emptyColumn) {
585                                hideColumn(column, true);
586                        }
587                }
588
589        }
590
591        /**
592         *
593         * @param row
594         * @param hide
595         */
596        public void hideRow(String row, boolean hide) {
597                HeaderInfo rowInfo = rowLookup.get(row);
598                rowInfo.setHide(hide);
599        }
600
601        /**
602         *
603         * @param column
604         * @param hide
605         */
606        public void hideColumn(String column, boolean hide) {
607                HeaderInfo colInfo = columnLookup.get(column);
608                colInfo.setHide(hide);
609        }
610
611        /**
612         * Change values in a column where 0 = something and 1 = something different
613         *
614         * @param column
615         * @param values
616         * @throws Exception
617         */
618        public void replaceColumnValues(String column, HashMap<String, String> values) throws Exception {
619                for (String row : rowLookup.keySet()) {
620                        String oldValue = this.getCell(row, column);
621                        String newValue = values.get(oldValue);
622                        this.addCell(row, column, newValue);
623                }
624
625        }
626
627        /**
628         * Apply filter to a column to change values from say numberic to nominal
629         * based on some range
630         *
631         * @param column
632         * @param changeValue
633         * @throws Exception
634         */
635        public void applyColumnFilter(String column, ChangeValue changeValue) throws Exception {
636                for (String row : rowLookup.keySet()) {
637                        String oldValue = this.getCell(row, column);
638                        String newValue = changeValue.change(oldValue);
639                        this.addCell(row, column, newValue);
640                }
641        }
642
643        /**
644         *
645         * @param column
646         * @param defaultValue
647         */
648        public void addColumn(String column, String defaultValue) {
649                ArrayList<String> columns = new ArrayList<String>();
650                columns.add(column);
651                addColumns(columns, defaultValue);
652        }
653
654        /**
655         * Add columns to worksheet and set default value
656         *
657         * @param columns
658         * @param defaultValue
659         */
660        public void addColumns(ArrayList<String> columns, String defaultValue) {
661                CompactCharSequence dv = new CompactCharSequence(defaultValue);
662                for (int i = 0; i < data.length; i++) {
663                        CompactCharSequence[] row = data[i];
664                        int oldrowlength = data[i].length;
665                        data[i] = (CompactCharSequence[]) resizeArray(row, oldrowlength + columns.size());
666                        for (int c = 0; c < columns.size(); c++) {
667                                data[i][oldrowlength + c] = dv;
668                        }
669                        if (i == 0) {
670                                for (int c = 0; c < columns.size(); c++) {
671                                        String column = columns.get(c);
672                                        data[0][oldrowlength + c] = new CompactCharSequence(column);
673                                        columnLookup.put(column, new HeaderInfo(oldrowlength + c));
674                                }
675                        }
676                }
677                //   columnLookup.get("ZNF30");
678
679                //     int startIndex = columnLookup.size() + 1;
680                //     for (String column : columns) {
681                //        if(column.equals("ttr")){
682                //            int dummy = 1;
683                //        }
684                //        columnLookup.put(column, new HeaderInfo(startIndex));
685                //        startIndex++;
686                //    }
687
688
689        }
690
691        /**
692         *
693         * @param row
694         * @param defaultValue
695         */
696        public void addRow(String row, String defaultValue) {
697                ArrayList<String> rows = new ArrayList<String>();
698                rows.add(row);
699                addRows(rows, defaultValue);
700        }
701
702        /**
703         * Add rows to the worksheet and fill in default value
704         *
705         * @param rows
706         * @param defaultValue
707         */
708        public void addRows(ArrayList<String> rows, String defaultValue) {
709                CompactCharSequence dv = new CompactCharSequence(defaultValue);
710                int oldlength = data.length;
711                int numColumns = 0;
712                if (data.length > 0 && data[0] != null) {
713                        numColumns = data[0].length;
714                }
715                data = (CompactCharSequence[][]) resizeArray(data, data.length + rows.size());
716                for (int r = 0; r < rows.size(); r++) {
717                        data[oldlength + r] = new CompactCharSequence[numColumns];
718                        for (int c = 0; c < numColumns; c++) {
719                                data[oldlength + r][c] = dv;
720                        }
721                        data[oldlength + r][0] = new CompactCharSequence(rows.get(r));
722                        rowLookup.put(rows.get(r), new HeaderInfo(r + oldlength));
723                }
724        }
725
726        /**
727         * Reallocates an array with a new size, and copies the contents of the old
728         * array to the new array.
729         *
730         * @param oldArray the old array, to be reallocated.
731         * @param newSize the new array size.
732         * @return A new array with the same contents.
733         */
734        private static Object resizeArray(Object oldArray, int newSize) {
735                int oldSize = java.lang.reflect.Array.getLength(oldArray);
736                Class<?> elementType = oldArray.getClass().getComponentType();
737                Object newArray = java.lang.reflect.Array.newInstance(
738                                elementType, newSize);
739                int preserveLength = Math.min(oldSize, newSize);
740                if (preserveLength > 0) {
741                        System.arraycopy(oldArray, 0, newArray, 0, preserveLength);
742                }
743                return newArray;
744        }
745
746        /**
747         * Add data to a cell
748         *
749         * @param row
750         * @param col
751         * @param value
752         * @throws Exception
753         */
754        public void addCell(String row, String col, String value) throws Exception {
755                HeaderInfo rowIndex = rowLookup.get(row);
756                HeaderInfo colIndex = columnLookup.get(col);
757                if (rowIndex == null) {
758                        throw new Exception("Row " + row + " not found in worksheet");
759                }
760                if (colIndex == null) {
761                        throw new Exception("Column " + col + " not found in worksheet");
762                }
763
764
765                data[rowIndex.getIndex()][colIndex.getIndex()] = new CompactCharSequence(value);
766        }
767
768        /**
769         *
770         * @param row
771         * @return
772         */
773        public boolean isValidRow(String row) {
774                HeaderInfo rowIndex = rowLookup.get(row);
775                if (rowIndex == null) {
776                        for (String rowtable : rowLookup.keySet()) {
777                                if (row.equalsIgnoreCase(rowtable)) {
778
779                                        return true;
780                                }
781                        }
782                        return false;
783                } else {
784                        return true;
785                }
786        }
787
788        /**
789         *
790         * @param col
791         * @return
792         */
793        public boolean isValidColumn(String col) {
794                HeaderInfo colIndex = columnLookup.get(col);
795                if (colIndex == null) {
796                        for (String coltable : columnLookup.keySet()) {
797                                if (col.equalsIgnoreCase(coltable)) {
798
799                                        return true;
800                                }
801                        }
802
803                        return false;
804
805
806                } else {
807                        return true;
808                }
809        }
810        //When we do gene signatures we ask for the same data value often. This method took up 50% of the time.
811        HashMap<String, Double> doubleValues = new HashMap<String, Double>();
812        boolean cacheDoubleValues = false;
813
814        /**
815         *
816         * @param value
817         */
818        public void setCacheDoubleValues(boolean value) {
819                cacheDoubleValues = value;
820        }
821
822        /**
823         *
824         * @param row
825         * @param col
826         * @return
827         * @throws Exception
828         */
829        public Double getCellDouble(String row, String col) throws Exception {
830                if (cacheDoubleValues) {
831                        String key = row + ":" + col;
832
833                        Double v = doubleValues.get(key);
834                        if (v != null) {
835                                return v;
836                        }
837                        String value = getCell(row, col);
838
839                        try {
840                                v = Double.parseDouble(value);
841                        } catch (Exception e) {
842                        }
843                        doubleValues.put(key, v);
844                        return v;
845                } else {
846                        Double v = null;
847                        String value = getCell(row, col);
848                        try {
849                                v = Double.parseDouble(value);
850                        } catch (Exception e) {
851                        }
852                        return v;
853                }
854
855        }
856
857        /**
858         * Get cell value
859         *
860         * @param row
861         * @param col
862         * @return
863         * @throws Exception
864         */
865        public String getCell(String row, String col) throws Exception {
866                if (col.equals(this.getIndexColumnName())) {
867                        return row;
868                }
869                HeaderInfo rowIndex = rowLookup.get(row);
870                HeaderInfo colIndex = columnLookup.get(col);
871
872                if (rowIndex == null) {
873                        //allow for case insentive search
874                        for (String rowtable : rowLookup.keySet()) {
875                                if (row.equalsIgnoreCase(rowtable)) {
876                                        rowIndex = rowLookup.get(rowtable);
877                                        break;
878                                }
879                        }
880                        if (rowIndex == null) {
881                                throw new Exception("Row " + row + " not found in worksheet");
882                        }
883                }
884                if (colIndex == null) {
885                        //allow for case insentive search
886                        for (String coltable : columnLookup.keySet()) {
887                                if (col.equalsIgnoreCase(coltable)) {
888                                        colIndex = columnLookup.get(coltable);
889                                        break;
890                                }
891                        }
892                        if (colIndex == null) {
893                                throw new Exception("Column " + col + " not found in worksheet");
894                        }
895                }
896
897                CompactCharSequence ccs = data[rowIndex.getIndex()][colIndex.getIndex()];
898                if (ccs != null) {
899                        return ccs.toString();
900                } else {
901                        return "";
902                }
903
904                // return .toString();
905        }
906
907        /**
908         *
909         * @param changeValue
910         */
911        public void changeRowHeader(ChangeValue changeValue) {
912                ArrayList<String> rows = new ArrayList<String>(rowLookup.keySet());
913                for (String row : rows) {
914                        String newRow = changeValue.change(row);
915                        HeaderInfo value = rowLookup.get(row);
916                        rowLookup.remove(row);
917                        rowLookup.put(newRow, value);
918                }
919        }
920
921        /**
922         *
923         * @param changeValue
924         */
925        public void changeColumnHeader(ChangeValue changeValue) {
926                ArrayList<String> columns = new ArrayList<String>(columnLookup.keySet());
927                for (String col : columns) {
928                        String newCol = changeValue.change(col);
929                        HeaderInfo value = columnLookup.get(col);
930                        columnLookup.remove(col);
931                        columnLookup.put(newCol, value);
932                }
933        }
934
935        /**
936         *
937         * @param row
938         * @param newRow
939         * @throws Exception
940         */
941        public void changeRowHeader(String row, String newRow) throws Exception {
942                HeaderInfo value = rowLookup.get(row);
943                if (value == null) {
944                        throw new Exception("Row not found " + row);
945                }
946                rowLookup.remove(row);
947                rowLookup.put(newRow, value);
948                if (this.isMetaDataRow(row)) {
949                        metaDataRowsHashMap.remove(row);
950                        metaDataRowsHashMap.put(newRow, newRow);
951                }
952        }
953
954        /**
955         * Change the columns in the HashMap Key to the name of the value
956         *
957         * @param newColumnValues
958         * @throws Exception
959         */
960        public void changeColumnsHeaders(LinkedHashMap<String, String> newColumnValues) throws Exception {
961                for (String oldColumn : newColumnValues.keySet()) {
962                        String newColumn = newColumnValues.get(oldColumn);
963                        changeColumnHeader(oldColumn, newColumn);
964                }
965
966        }
967
968        /**
969         *
970         * @param col
971         * @param newCol
972         * @throws Exception
973         */
974        public void changeColumnHeader(String col, String newCol) throws Exception {
975                HeaderInfo value = columnLookup.get(col);
976                if (value == null) {
977                        throw new Exception("Column not found " + col);
978                }
979                columnLookup.remove(col);
980                columnLookup.put(newCol, value);
981                if (this.isMetaDataColumn(col)) {
982                        metaDataColumnsHashMap.remove(col);
983                        metaDataColumnsHashMap.put(newCol, newCol);
984                }
985
986        }
987
988        /**
989         *
990         * @param column
991         * @return
992         * @throws Exception
993         */
994        public Integer getColumnIndex(String column) throws Exception {
995                HeaderInfo headerInfo = columnLookup.get(column);
996                if (headerInfo == null) {
997                        throw new Exception("Column " + column + " not found");
998                }
999                return headerInfo.getIndex();
1000        }
1001
1002        /**
1003         *
1004         * @param row
1005         * @return
1006         * @throws Exception
1007         */
1008        public Integer getRowIndex(String row) throws Exception {
1009                HeaderInfo headerInfo = rowLookup.get(row);
1010                if (headerInfo == null) {
1011                        throw new Exception("Row " + row + " not found");
1012                }
1013                return headerInfo.getIndex();
1014        }
1015
1016        /**
1017         *
1018         * @param number
1019         * @return
1020         */
1021        public ArrayList<String> getRandomDataColumns(int number) {
1022                ArrayList<String> columns = getDataColumns();
1023                return getRandomDataColumns(number, columns);
1024        }
1025
1026        /**
1027         *
1028         * @param number
1029         * @param columns
1030         * @return
1031         */
1032        public ArrayList<String> getRandomDataColumns(int number, ArrayList<String> columns) {
1033                ArrayList<String> randomColumns = new ArrayList<String>();
1034                HashMap<String, String> picked = new HashMap<String, String>();
1035                while (picked.size() < number) {
1036                        double v = Math.random();
1037                        int index = (int) (v * columns.size());
1038                        if (picked.containsKey(String.valueOf(index))) {
1039                                continue;
1040                        }
1041                        picked.put(String.valueOf(index), String.valueOf(index));
1042                        randomColumns.add(columns.get(index));
1043                }
1044                return randomColumns;
1045
1046        }
1047
1048        /**
1049         * Get the list of column names including those that may be hidden
1050         *
1051         * @return
1052         */
1053        public ArrayList<String> getAllColumns() {
1054                ArrayList<String> columns = new ArrayList<String>();
1055                for (String col : columnLookup.keySet()) {
1056                        columns.add(col);
1057                }
1058                return columns;
1059        }
1060
1061        /**
1062         * Get the list of column names. Does not include hidden columns
1063         *
1064         * @return
1065         */
1066        public ArrayList<String> getColumns() {
1067                ArrayList<String> columns = new ArrayList<String>();
1068                for (String col : columnLookup.keySet()) {
1069                        HeaderInfo hi = columnLookup.get(col);
1070                        if (!hi.isHide()) {
1071                                columns.add(col);
1072                        }
1073                }
1074                return columns;
1075        }
1076
1077        /**
1078         * Get back a list of unique values in the column
1079         *
1080         * @param column
1081         * @return
1082         * @throws Exception
1083         */
1084        public ArrayList<String> getDiscreteColumnValues(String column) throws Exception {
1085                HashMap<String, String> hashMapValues = new HashMap<String, String>();
1086                ArrayList<String> values = new ArrayList<String>();
1087                ArrayList<String> rows = getDataRows();
1088                for (String row : rows) {
1089                        String value = getCell(row, column);
1090                        if (!hashMapValues.containsKey(value)) {
1091                                hashMapValues.put(value, value);
1092                                values.add(value);
1093                        }
1094                }
1095                return values;
1096        }
1097
1098        /**
1099         * Get back a list of unique values in the row
1100         *
1101         * @param row
1102         * @return
1103         * @throws Exception
1104         */
1105        public ArrayList<String> getDiscreteRowValues(String row) throws Exception {
1106                HashMap<String, String> hashMapValues = new HashMap<String, String>();
1107                ArrayList<String> values = new ArrayList<String>();
1108                for (String column : getColumns()) {
1109                        String value = getCell(row, column);
1110                        if (!hashMapValues.containsKey(value)) {
1111                                hashMapValues.put(value, value);
1112                                values.add(value);
1113                        }
1114                }
1115                return values;
1116        }
1117
1118        /**
1119         * Get all rows including those that may be hidden
1120         *
1121         * @return
1122         */
1123        public ArrayList<String> getAllRows() {
1124                ArrayList<String> rows = new ArrayList<String>();
1125                for (String row : rowLookup.keySet()) {
1126                        rows.add(row);
1127                }
1128                return rows;
1129
1130        }
1131
1132        /**
1133         * Get the list of row names. Will exclude hidden values
1134         *
1135         * @return
1136         */
1137        public ArrayList<String> getRows() {
1138                ArrayList<String> rows = new ArrayList<String>();
1139                for (String row : rowLookup.keySet()) {
1140                        HeaderInfo hi = rowLookup.get(row);
1141                        if (!hi.isHide()) {
1142                                rows.add(row);
1143                        }
1144                }
1145                return rows;
1146        }
1147
1148        /**
1149         * Get the list of row names
1150         *
1151         * @return
1152         */
1153        public ArrayList<String> getDataRows() {
1154                ArrayList<String> rows = new ArrayList<String>();
1155                for (String row : rowLookup.keySet()) {
1156                        if (this.isMetaDataRow(row)) {
1157                                continue;
1158                        }
1159                        HeaderInfo hi = rowLookup.get(row);
1160                        if (!hi.isHide()) {
1161                                rows.add(row);
1162                        }
1163                }
1164                return rows;
1165        }
1166
1167        /**
1168         * Get the log scale of this worksheet where a zero value will be set to .1
1169         * as Log(0) is undefined
1170         *
1171         * @param base
1172         * @return
1173         * @throws Exception
1174         */
1175        public WorkSheet getLogScale(double base) throws Exception {
1176                return getLogScale(base, .1);
1177
1178        }
1179
1180        /**
1181         * Get the log scale of this worksheet
1182         *
1183         * @param base
1184         * @return
1185         * @throws Exception
1186         */
1187        public WorkSheet getLogScale(double base, double zeroValue) throws Exception {
1188
1189                WorkSheet workSheet = new WorkSheet(getRows(), getColumns());
1190                workSheet.setIndexColumnName(this.getIndexColumnName());
1191                ArrayList<String> rows = getRows();
1192                ArrayList<String> columns = getColumns();
1193                for (String row : rows) {
1194                        for (String col : columns) {
1195                                if (this.isMetaDataColumn(col) || this.isMetaDataRow(row)) {
1196                                        String value = getCell(row, col);
1197                                        workSheet.addCell(row, col, value);
1198                                } else {
1199                                        String value = getCell(row, col);
1200                                        try {
1201                                                Double d = Double.parseDouble(value);
1202                                                if (d == 0.0) {
1203                                                        d = zeroValue;
1204                                                } else {
1205                                                        d = Math.log(d) / Math.log(base);
1206                                                }
1207                                                workSheet.addCell(row, col, d + "");
1208                                        } catch (Exception e) {
1209                                                workSheet.addCell(row, col, value);
1210                                        }
1211
1212                                }
1213                        }
1214                }
1215
1216                ArrayList<String> metadataRows = this.getMetaDataRows();
1217                ArrayList<String> metadataColumns = this.getMetaDataColumns();
1218                workSheet.setMetaDataColumns(metadataColumns);
1219                workSheet.setMetaDataRows(metadataRows);
1220                return workSheet;
1221        }
1222
1223        /**
1224         * Swap the row and columns returning a new worksheet
1225         *
1226         * @return
1227         * @throws Exception
1228         */
1229        public WorkSheet swapRowAndColumns() throws Exception {
1230
1231                WorkSheet swappedWorkSheet = new WorkSheet(getColumns(), getRows());
1232                for (String row : getRows()) {
1233                        for (String col : getColumns()) {
1234                                String value = getCell(row, col);
1235                                swappedWorkSheet.addCell(col, row, value);
1236                        }
1237                }
1238
1239                ArrayList<String> metadataRows = this.getMetaDataRows();
1240                ArrayList<String> metadataColumns = this.getMetaDataColumns();
1241                swappedWorkSheet.setMetaDataColumns(metadataRows);
1242                swappedWorkSheet.setMetaDataRows(metadataColumns);
1243                return swappedWorkSheet;
1244        }
1245
1246        static CompactCharSequence[][] getAllValuesCompactCharSequence(File fileName, char delimiter) throws Exception {
1247                FileInputStream fi = new FileInputStream(fileName);
1248                return getAllValuesCompactCharSequence(fi, delimiter);
1249        }
1250
1251        /**
1252         * All support for loading from a jar file
1253         *
1254         * @param is
1255         * @param delimiter
1256         * @return
1257         * @throws Exception
1258         */
1259        static CompactCharSequence[][] getAllValuesCompactCharSequence(InputStream is, char delimiter) throws Exception {
1260                // FileReader reader = new FileReader(fileName);
1261
1262                BufferedReader br = new BufferedReader(new InputStreamReader(is));
1263
1264
1265                ArrayList<CompactCharSequence[]> rows = new ArrayList<CompactCharSequence[]>();
1266
1267                String line = br.readLine();
1268                int numcolumns = -1;
1269                while (line != null) {
1270                        String[] d = line.split(String.valueOf(delimiter));
1271                        if (numcolumns == -1) {
1272                                numcolumns = d.length;
1273                        }
1274                        CompactCharSequence[] ccs = new CompactCharSequence[d.length];
1275                        for (int i = 0; i < d.length; i++) {
1276                                ccs[i] = new CompactCharSequence(d[i]);
1277                        }
1278                        rows.add(ccs);
1279
1280                        line = br.readLine();
1281                }
1282                br.close();
1283                // reader.close();
1284
1285                CompactCharSequence[][] data = new CompactCharSequence[rows.size()][numcolumns];
1286                for (int i = 0; i < rows.size(); i++) {
1287                        CompactCharSequence[] row = rows.get(i);
1288                        for (int j = 0; j < row.length; j++) { //
1289                                if (row[j].length() > 1 && row[j].charAt(0) == '"') {
1290                                        // System.out.println(row[j]);
1291                                        if (row[j].length() > 2) {
1292                                                row[j] = new CompactCharSequence(row[j].subSequence(1, row[j].length() - 1).toString());
1293                                        } else {
1294                                                row[j] = new CompactCharSequence("");
1295                                        }
1296                                }
1297                                if (j < row.length && j < data[0].length) {
1298                                        data[i][j] = row[j];
1299                                }
1300                        }
1301
1302
1303                }
1304
1305                return data;
1306
1307        }
1308
1309        static String[][] getAllValues(String fileName, char delimiter) throws Exception {
1310                FileReader reader = new FileReader(fileName);
1311                BufferedReader br = new BufferedReader(reader);
1312                ArrayList<String[]> rows = new ArrayList<String[]>();
1313
1314                String line = br.readLine();
1315                int numcolumns = -1;
1316                while (line != null) {
1317                        String[] d = line.split(String.valueOf(delimiter));
1318                        if (numcolumns == -1) {
1319                                numcolumns = d.length;
1320                        }
1321                        rows.add(d);
1322
1323                        line = br.readLine();
1324                }
1325                br.close();
1326                reader.close();
1327
1328                String[][] data = new String[rows.size()][numcolumns];
1329                for (int i = 0; i < rows.size(); i++) {
1330                        String[] row = rows.get(i);
1331                        for (int j = 0; j < row.length; j++) {
1332                                if (row[j].startsWith("\"") && row[j].endsWith("\"")) {
1333                                        // System.out.println(row[j]);
1334                                        row[j] = row[j].substring(1, row[j].length() - 1);
1335                                }
1336                                data[i][j] = row[j];
1337                        }
1338
1339
1340                }
1341
1342                return data;
1343
1344        }
1345
1346        /**
1347         * Combine two work sheets where you join based on rows. Rows that are found
1348         * in one but not the other are removed. If the second sheet is meta data
1349         * then a meta data column will be added between the two joined columns
1350         *
1351         * @param w1FileName
1352         * @param w2FileName
1353         * @param delimitter
1354         * @param secondSheetMetaData
1355         * @return
1356         * @throws Exception
1357         */
1358        static public WorkSheet unionWorkSheetsRowJoin(String w1FileName, String w2FileName, char delimitter, boolean secondSheetMetaData) throws Exception {
1359                WorkSheet w1 = WorkSheet.readCSV(w1FileName, delimitter);
1360                WorkSheet w2 = WorkSheet.readCSV(w2FileName, delimitter);
1361                return unionWorkSheetsRowJoin(w1, w2, secondSheetMetaData);
1362
1363        }
1364
1365        /**
1366         * * Combine two work sheets where you join based on rows. Rows that are
1367         * found in one but not the other are removed. If the second sheet is meta
1368         * data then a meta data column will be added between the two joined columns
1369         *
1370         * @param w1
1371         * @param w2
1372         * @param secondSheetMetaData
1373         * @return
1374         * @throws Exception
1375         */
1376        static public WorkSheet unionWorkSheetsRowJoin(WorkSheet w1, WorkSheet w2, boolean secondSheetMetaData) throws Exception {
1377                ArrayList<String> w1Columns = w1.getColumns();
1378                ArrayList<String> w2Columns = w2.getColumns();
1379                ArrayList<String> w1DataColumns = w1.getDataColumns();
1380                ArrayList<String> w2DataColumns = w2.getDataColumns();
1381                ArrayList<String> w1MetaDataColumns = w1.getMetaDataColumns();
1382                ArrayList<String> w2MetaDataColumns = w2.getMetaDataColumns();
1383
1384
1385                if (secondSheetMetaData) {
1386                        if (!w1.getColumns().contains("META_DATA")) {
1387                                w1DataColumns.add("META_DATA");
1388                        }
1389                }
1390
1391                ArrayList<String> joinedColumns = new ArrayList<String>();
1392                joinedColumns.addAll(w1DataColumns);
1393                joinedColumns.addAll(w2DataColumns);
1394                if (!joinedColumns.contains("META_DATA") && (w1MetaDataColumns.size() > 0 || w2MetaDataColumns.size() > 0)) {
1395                        joinedColumns.add("META_DATA");
1396                }
1397                for (String column : w1MetaDataColumns) {
1398                        if (!joinedColumns.contains(column)) {
1399                                joinedColumns.add(column);
1400                        }
1401                }
1402                for (String column : w2MetaDataColumns) {
1403                        if (!joinedColumns.contains(column)) {
1404                                joinedColumns.add(column);
1405                        }
1406                }
1407                ArrayList<String> w1Rows = w1.getRows();
1408                ArrayList<String> w2Rows = w2.getRows();
1409                ArrayList<String> rows = new ArrayList<String>();
1410
1411                HashSet<String> w1Key = new HashSet<String>(w1Rows);
1412                for (String key : w2Rows) {
1413                        if (w1Key.contains(key)) {
1414                                rows.add(key);
1415                        }
1416                }
1417
1418                WorkSheet worksheet = new WorkSheet(rows, joinedColumns);
1419
1420                for (String row : rows) {
1421                        for (String column : w1Columns) {
1422                                if (column.equals("META_DATA")) {
1423                                        continue;
1424                                }
1425                                String value = w1.getCell(row, column);
1426                                worksheet.addCell(row, column, value);
1427                        }
1428                }
1429
1430                for (String row : rows) {
1431                        for (String column : w2Columns) {
1432                                if (column.equals("META_DATA")) {
1433                                        continue;
1434                                }
1435                                String value = w2.getCell(row, column);
1436                                worksheet.addCell(row, column, value);
1437                        }
1438                }
1439                worksheet.setMetaDataColumnsAfterColumn();
1440                worksheet.setMetaDataRowsAfterRow();
1441                return worksheet;
1442        }
1443
1444        /**
1445         * Read a CSV/Tab delimitted file where you pass in the delimiter
1446         *
1447         * @param fileName
1448         * @param delimiter
1449         * @return
1450         * @throws Exception
1451         */
1452        static public WorkSheet readCSV(String fileName, char delimiter) throws Exception {
1453
1454
1455                return readCSV(new File(fileName), delimiter);
1456        }
1457
1458        static public WorkSheet readCSV(File f, char delimiter) throws Exception {
1459
1460
1461                return readCSV(new FileInputStream(f), delimiter);
1462        }
1463
1464        /**
1465         * Read a CSV/Tab delimited file where you pass in the delimiter
1466         *
1467         * @param f
1468         * @param delimiter
1469         * @return
1470         * @throws Exception
1471         */
1472        static public WorkSheet readCSV(InputStream is, char delimiter) throws Exception {
1473
1474
1475                CompactCharSequence[][] data = getAllValuesCompactCharSequence(is, delimiter);
1476
1477                WorkSheet workSheet = new WorkSheet(data);
1478                workSheet.setMetaDataColumnsAfterColumn();
1479                workSheet.setMetaDataRowsAfterRow();
1480                return workSheet;
1481        }
1482
1483        /**
1484         * Save the worksheet as a csv file
1485         *
1486         * @param fileName
1487         * @throws Exception
1488         */
1489        public void saveCSV(String fileName) throws Exception {
1490                File f = new File(fileName);
1491                File parentFile = f.getParentFile();
1492                if (!parentFile.isDirectory()) {
1493                        parentFile.mkdirs();
1494                }
1495                FileOutputStream file = new FileOutputStream(fileName);
1496                BufferedOutputStream bs = new BufferedOutputStream(file);
1497                save(bs, ',', false);
1498                bs.close();
1499                file.close();
1500        }
1501
1502        /**
1503         *
1504         * @param fileName
1505         * @throws Exception
1506         */
1507        public void saveTXT(String fileName) throws Exception {
1508                File f = new File(fileName);
1509                File parentFile = f.getParentFile();
1510                if (!parentFile.isDirectory()) {
1511                        parentFile.mkdirs();
1512                }
1513                FileOutputStream file = new FileOutputStream(fileName);
1514                BufferedOutputStream bs = new BufferedOutputStream(file);
1515                save(bs, '\t', false);
1516                bs.close();
1517                file.close();
1518        }
1519        private String rowHeader = "REF";
1520
1521        /**
1522         *
1523         * @param value
1524         */
1525        public void setRowHeader(String value) {
1526                rowHeader = value;
1527        }
1528
1529        /**
1530         * Add columns from a second worksheet to be joined by common row. If the
1531         * appended worksheet doesn't contain a row in the master worksheet then
1532         * default value of "" is used. Rows in the appended worksheet not found in
1533         * the master worksheet are not added.
1534         *
1535         * @param worksheet
1536         * @throws Exception
1537         */
1538        public void appendWorkSheetColumns(WorkSheet worksheet) throws Exception {
1539
1540                ArrayList<String> newColumns = worksheet.getColumns();
1541
1542                this.addColumns(newColumns, "");
1543                ArrayList<String> rows = this.getRows();
1544                for (String row : rows) {
1545                        for (String col : newColumns) {
1546                                if (worksheet.isValidRow(row)) {
1547                                        String value = worksheet.getCell(row, col);
1548                                        this.addCell(row, col, value);
1549                                }
1550
1551                        }
1552                }
1553
1554
1555
1556        }
1557
1558        /**
1559         * Add rows from a second worksheet to be joined by common column. If the
1560         * appended worksheet doesn't contain a column in the master worksheet then
1561         * default value of "" is used. Columns in the appended worksheet not found
1562         * in the master worksheet are not added.
1563         *
1564         * @param worksheet
1565         * @throws Exception
1566         */
1567        public void appendWorkSheetRows(WorkSheet worksheet) throws Exception {
1568
1569                ArrayList<String> newRows = worksheet.getRows();
1570
1571                this.addRows(newRows, "");
1572                for (String col : this.getColumns()) {
1573                        if (!worksheet.isValidColumn(col)) {
1574                                continue;
1575                        }
1576                        for (String row : newRows) {
1577                                if (worksheet.isValidColumn(col)) {
1578                                        String value = worksheet.getCell(row, col);
1579                                        this.addCell(row, col, value);
1580                                }
1581
1582                        }
1583                }
1584
1585        }
1586
1587        /**
1588         *
1589         * @param outputStream
1590         * @param delimitter
1591         * @param quoteit
1592         * @throws Exception
1593         */
1594        public void save(OutputStream outputStream, char delimitter, boolean quoteit) throws Exception {
1595                outputStream.write(rowHeader.getBytes());
1596                //String quote = "\"";
1597
1598                for (String col : getColumns()) {
1599                        outputStream.write(delimitter);
1600                        if (quoteit) {
1601                                outputStream.write('"');
1602                        }
1603                        outputStream.write(col.getBytes());
1604                        if (quoteit) {
1605                                outputStream.write('"');
1606                        }
1607                }
1608                outputStream.write("\r\n".getBytes());
1609                for (String row : getRows()) {
1610                        if (quoteit) {
1611                                outputStream.write('"');
1612                        }
1613                        outputStream.write(row.getBytes());
1614                        if (quoteit) {
1615                                outputStream.write('"');
1616                        }
1617                        for (String col : getColumns()) {
1618                                // try{
1619                                String value = getCell(row, col);
1620                                outputStream.write(delimitter);
1621                                if (!this.isMetaDataColumn(col) && !this.isMetaDataRow(row)) {
1622                                        if (value == null || value.length() == 0 || value.equalsIgnoreCase("null")) {
1623                                                value = "NaN";
1624                                        }
1625                                } else {
1626                                        if (value == null || value.length() == 0 || value.equalsIgnoreCase("null")) {
1627                                                value = "";
1628                                        }
1629                                }
1630
1631                                outputStream.write(value.getBytes());
1632                                //  }catch(Exception e){
1633                                //      System.out.println(row + " " + col);
1634                                //  }
1635                        }
1636                        outputStream.write("\r\n".getBytes());
1637                }
1638        }
1639
1640        /**
1641         * @return the indexColumnName
1642         */
1643        public String getIndexColumnName() {
1644                return indexColumnName;
1645        }
1646
1647        /**
1648         * @param indexColumnName the indexColumnName to set
1649         */
1650        public void setIndexColumnName(String indexColumnName) {
1651                this.indexColumnName = indexColumnName;
1652        }
1653
1654        /**
1655         * @return the columnLookup
1656         */
1657        public LinkedHashMap<String, HeaderInfo> getColumnLookup() {
1658                return columnLookup;
1659        }
1660
1661        /**
1662         * @return the rowLookup
1663         */
1664        public LinkedHashMap<String, HeaderInfo> getRowLookup() {
1665                return rowLookup;
1666        }
1667
1668        /**
1669         * @return the metaDataColumnsHashMap
1670         */
1671        public LinkedHashMap<String, String> getMetaDataColumnsHashMap() {
1672                return metaDataColumnsHashMap;
1673        }
1674
1675        /**
1676         * @return the metaDataRowsHashMap
1677         */
1678        public LinkedHashMap<String, String> getMetaDataRowsHashMap() {
1679                return metaDataRowsHashMap;
1680        }
1681
1682        /**
1683         * @return the rowHeader
1684         */
1685        public String getRowHeader() {
1686                return rowHeader;
1687        }
1688}