001 package org.ujmp.core.util; 002 003 import java.text.DateFormat; 004 import java.text.DecimalFormat; 005 import java.text.DecimalFormatSymbols; 006 import java.text.FieldPosition; 007 import java.text.Format; 008 import java.text.NumberFormat; 009 import java.text.ParsePosition; 010 import java.text.SimpleDateFormat; 011 import java.util.Date; 012 013 import org.ujmp.core.Coordinates; 014 import org.ujmp.core.Matrix; 015 import org.ujmp.core.bigdecimalmatrix.BigDecimalMatrix; 016 import org.ujmp.core.datematrix.DateMatrix; 017 import org.ujmp.core.exceptions.MatrixException; 018 019 public class UJMPFormat extends Format { 020 private static final long serialVersionUID = -557618747324763226L; 021 022 private static UJMPFormat multiLineInstance = new UJMPFormat(true, 10, true); 023 024 private static UJMPFormat singleLineInstance = new UJMPFormat(false, 100, false); 025 026 private NumberFormat defaultNumberFormat = null; 027 028 private NumberFormat exponentialNumberFormat = null; 029 030 private DateFormat dateFormat = null; 031 032 private boolean multiLine = true; 033 034 private boolean usePadding = false; 035 036 private int width = 10; 037 038 public UJMPFormat(boolean multiLine, int width, boolean usePadding) { 039 DecimalFormatSymbols symbols = new DecimalFormatSymbols(UJMPSettings.getLocale()); 040 symbols.setNaN("NaN"); 041 symbols.setInfinity("Inf"); 042 defaultNumberFormat = new DecimalFormat("0.0000", symbols); 043 exponentialNumberFormat = new DecimalFormat("0.000E000", symbols); 044 dateFormat = new SimpleDateFormat("yyyy-mm-dd"); 045 this.multiLine = multiLine; 046 this.width = width; 047 this.usePadding = usePadding; 048 } 049 050 public static final UJMPFormat getMultiLineInstance() { 051 return multiLineInstance; 052 } 053 054 public static final UJMPFormat getSingleLineInstance() { 055 return singleLineInstance; 056 } 057 058 @Override 059 public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { 060 if (obj == null) { 061 if (usePadding) { 062 pad(toAppendTo, ' ', width); 063 } 064 return toAppendTo; 065 } else if (obj instanceof String) { 066 return format((String) obj, toAppendTo, pos); 067 } else if (obj instanceof Matrix) { 068 return format((Matrix) obj, toAppendTo, pos); 069 } else if (obj instanceof Date) { 070 return format((Date) obj, toAppendTo, pos); 071 } else if (obj instanceof Number) { 072 return format((Number) obj, toAppendTo, pos); 073 } else { 074 return format(String.valueOf(obj), toAppendTo, pos); 075 } 076 } 077 078 private StringBuffer format(Matrix obj, StringBuffer toAppendTo, FieldPosition pos) { 079 if (obj == null) { 080 if (usePadding) { 081 pad(toAppendTo, ' ', width); 082 } 083 return toAppendTo; 084 } else if (obj.isScalar()) { 085 Object v = obj.getAsObject(obj.allCoordinates().iterator().next()); 086 return format(v, toAppendTo, pos); 087 } else if (multiLine) { 088 return formatMultiLine(obj, toAppendTo, pos); 089 } else { 090 toAppendTo.append("[Matrix]"); 091 return toAppendTo; 092 } 093 } 094 095 private StringBuffer format(Date obj, StringBuffer toAppendTo, FieldPosition pos) { 096 int length = toAppendTo.length(); 097 toAppendTo = dateFormat.format(obj, toAppendTo, pos); 098 length = width - (toAppendTo.length() - length); 099 if (usePadding) { 100 pad(toAppendTo, ' ', length); 101 } 102 return toAppendTo; 103 } 104 105 private StringBuffer pad(StringBuffer s, char c, int count) { 106 for (int i = 0; i < count; i++) { 107 s.append(c); 108 } 109 return s; 110 } 111 112 private StringBuffer format(String obj, StringBuffer toAppendTo, FieldPosition pos) { 113 if (obj != null && obj.length() > width) { 114 obj = obj.substring(0, width); 115 } 116 if (obj != null) { 117 toAppendTo.append(obj); 118 if (usePadding) { 119 pad(toAppendTo, ' ', width - obj.length()); 120 } 121 return toAppendTo; 122 } else { 123 if (usePadding) { 124 pad(toAppendTo, ' ', width); 125 } 126 return toAppendTo; 127 } 128 } 129 130 private StringBuffer format(Number obj, StringBuffer toAppendTo, FieldPosition pos) { 131 String s = defaultNumberFormat.format(obj); 132 if (s.length() > width) { 133 s = exponentialNumberFormat.format(obj); 134 } 135 if (usePadding) { 136 pad(toAppendTo, ' ', width - s.length()); 137 } 138 toAppendTo.append(s); 139 return toAppendTo; 140 } 141 142 private StringBuffer formatMultiLine(Matrix m, StringBuffer toAppendTo, FieldPosition pos) { 143 long maxRows = UJMPSettings.getMaxRowsToPrint(); 144 long maxColumns = UJMPSettings.getMaxColumnsToPrint(); 145 146 final String EOL = System.getProperty("line.separator"); 147 148 long rowCount = m.getRowCount(); 149 long columnCount = m.getColumnCount(); 150 long[] cursor = new long[m.getDimensionCount()]; 151 152 if (m.getDimensionCount() > 2) { 153 toAppendTo.append(m.getDimensionCount()); 154 toAppendTo.append("D-Matrix ["); 155 toAppendTo.append(Coordinates.toString('x', m.getSize())); 156 toAppendTo.append("]: only two dimensions are printed"); 157 toAppendTo.append(EOL); 158 } 159 160 if (m.getAnnotation() != null) { 161 format(m.getLabel(), toAppendTo, pos); 162 toAppendTo.append(" "); 163 for (int col = 0; col < columnCount && col < maxColumns; col++) { 164 format(m.getColumnLabel(col), toAppendTo, pos); 165 if (col < columnCount - 1) { 166 toAppendTo.append(' '); 167 } 168 } 169 toAppendTo.append(EOL); 170 pad(toAppendTo, '=', width); 171 toAppendTo.append(" "); 172 for (int col = 0; col < columnCount && col < maxColumns; col++) { 173 pad(toAppendTo, '-', width); 174 if (col < columnCount - 1) { 175 toAppendTo.append(' '); 176 } 177 } 178 toAppendTo.append(EOL); 179 } 180 181 for (cursor[Matrix.ROW] = 0; cursor[Matrix.ROW] < rowCount && cursor[Matrix.ROW] < maxRows; cursor[Matrix.ROW]++) { 182 if (m.getAnnotation() != null) { 183 format(m.getRowLabel(cursor[Matrix.ROW]), toAppendTo, pos); 184 toAppendTo.append(" | "); 185 } 186 for (cursor[Matrix.COLUMN] = 0; cursor[Matrix.COLUMN] < columnCount 187 && cursor[Matrix.COLUMN] < maxColumns; cursor[Matrix.COLUMN]++) { 188 Object o = m.getAsObject(cursor); 189 if (o == null && (m instanceof BigDecimalMatrix || m instanceof DateMatrix)) { 190 toAppendTo = format(Double.NaN, toAppendTo, pos); 191 } else { 192 toAppendTo = format(o, toAppendTo, pos); 193 } 194 if (cursor[Matrix.COLUMN] < columnCount - 1) { 195 toAppendTo.append(' '); 196 } 197 } 198 toAppendTo.append(EOL); 199 } 200 201 if (rowCount == 0 || columnCount == 0) { 202 toAppendTo.append("[" + rowCount + "x" + columnCount + "]" + EOL); 203 } else if (rowCount > UJMPSettings.getMaxRowsToPrint() 204 || columnCount > UJMPSettings.getMaxColumnsToPrint()) { 205 toAppendTo.append("[...]"); 206 } 207 208 return toAppendTo; 209 } 210 211 @Override 212 public Object parseObject(String source, ParsePosition pos) { 213 throw new MatrixException("not implemented"); 214 } 215 }