From ab848222575fc60a763fc69da169106d8295fe10 Mon Sep 17 00:00:00 2001 From: dzmipt Date: Sat, 23 Nov 2024 14:54:53 +0100 Subject: [PATCH] Adding element class to KBaseVector. Some refactoring. --- src/kx/KConnectionStats.java | 2 +- src/studio/kdb/K.java | 36 +++++++++++++++++++-------- src/studio/kdb/KTableModel.java | 4 +++ src/studio/kdb/Session.java | 2 +- src/studio/ui/ExcelExporter.java | 2 +- src/studio/ui/chart/Chart.java | 34 ++++++++++++------------- src/studio/ui/chart/KFormat.java | 34 ++++++++++++------------- test/studio/kdb/KTest.java | 19 +++++++++++++- test/studio/ui/ExcelExporterTest.java | 23 +++++++++++++++++ 9 files changed, 107 insertions(+), 49 deletions(-) create mode 100644 test/studio/ui/ExcelExporterTest.java diff --git a/src/kx/KConnectionStats.java b/src/kx/KConnectionStats.java index d5226cf9..24752fee 100644 --- a/src/kx/KConnectionStats.java +++ b/src/kx/KConnectionStats.java @@ -50,7 +50,7 @@ public synchronized void sentBytes(long count) { } public synchronized void receivedBytes(long count) { - lastQueryTime = K.KTimespan.period(lastQueryTimestamp, K.KTimestamp.now()); + lastQueryTime = lastQueryTimestamp.span(K.KTimestamp.now()); totalQueryTime = totalQueryTime.isNull() ? lastQueryTime : totalQueryTime.add(lastQueryTime); totalQueryTimeInCurrentSession = totalQueryTimeInCurrentSession.isNull() ? lastQueryTime : totalQueryTimeInCurrentSession.add(lastQueryTime); diff --git a/src/studio/kdb/K.java b/src/studio/kdb/K.java index c1a23570..7d9ea9c1 100755 --- a/src/studio/kdb/K.java +++ b/src/studio/kdb/K.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Array; +import java.lang.reflect.ParameterizedType; import java.sql.Time; import java.sql.Timestamp; import java.text.DecimalFormat; @@ -16,7 +17,10 @@ public class K { private final static SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy.MM.dd"); private final static SimpleDateFormat dateTimeFormatter = new SimpleDateFormat("yyyy.MM.dd'T'HH:mm:ss.SSS"); private final static SimpleDateFormat timestampFormatter = new SimpleDateFormat("yyyy.MM.dd'D'HH:mm:ss."); - + private final static long SEC_IN_DAY = 24 * 60 * 60; + private final static long MS_IN_DAY = 1000 * SEC_IN_DAY; + private final static long NS_IN_DAY = 1000_000_000 * SEC_IN_DAY; + private final static long NS_IN_MONTH = (long) (NS_IN_DAY*(365*4+1)/(12*4.0)); static { TimeZone gmtTimeZone = java.util.TimeZone.getTimeZone("GMT"); @@ -989,7 +993,11 @@ public StringBuilder format(StringBuilder builder, KFormatContext context) { } public Date toDate() { - return new Date(86400000L * (value + 10957)); + return new Date(MS_IN_DAY * (value + 10957)); + } + + public KTimestamp toTimestamp() { + return new KTimestamp(value * NS_IN_DAY); } } @@ -1114,6 +1122,10 @@ public static KTimestamp now() { return now(systemClock); } + public KTimespan span(KTimestamp t2) { + return new KTimespan(t2.value - value); + } + public String getDataType() { return "Timestamp"; } @@ -1129,15 +1141,15 @@ public StringBuilder format(StringBuilder builder, KFormatContext context) { else if (value == Long.MAX_VALUE) builder.append("0Wp"); else if (value == -Long.MAX_VALUE) builder.append("-0Wp"); else { - Timestamp ts = toTimestamp(); + Timestamp ts = toJavaTimestamp(); builder.append(timestampFormatter.format(ts)) .append(nsFormatter.format(ts.getNanos())); } return builder; } - public Timestamp toTimestamp() { - long k = 86400000L * 10957; + public Timestamp toJavaTimestamp() { + long k = MS_IN_DAY * 10957; long n = 1000000000L; long d = value < 0 ? (value + 1) / n - 1 : value / n; long ltime = value == Long.MIN_VALUE ? value : (k + 1000 * d); @@ -1396,10 +1408,6 @@ public static class KTimespan extends KLongBase { public final static KTimespan NULL = new KTimespan(NULL_VALUE); public final static KTimespan ZERO = new KTimespan(0); - public static KTimespan period(KTimestamp t0, KTimestamp t1) { - return new KTimespan(t1.value - t0.value); - } - public KTimespan(long x) { super(-16, x); } @@ -1424,9 +1432,9 @@ public StringBuilder format(StringBuilder builder, KFormatContext context) { jj = -jj; builder.append("-"); } - int d = ((int) (jj / 86400000000000L)); + int d = ((int) (jj / NS_IN_DAY)); if (d != 0) builder.append(d).append("D"); - builder.append(i2((int) ((jj % 86400000000000L) / 3600000000000L))) + builder.append(i2((int) ((jj % NS_IN_DAY) / 3600000000000L))) .append(":").append(i2((int) ((jj % 3600000000000L) / 60000000000L))) .append(":").append(i2((int) ((jj % 60000000000L) / 1000000000L))) .append(".").append(nsFormatter.format((int) (jj % 1000000000L))); @@ -1456,6 +1464,7 @@ public static abstract class KBaseVector extends KBase { private byte attr = 0; private final String typeName; private final String typeChar; + private final Class elementClass; protected KBaseVector(Object array, int type, String typeName, String typeChar) { super(type); @@ -1463,6 +1472,11 @@ protected KBaseVector(Object array, int type, String typeName, String typeChar) this.length = Array.getLength(array); this.typeName = typeName; this.typeChar = typeChar; + elementClass = (Class)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]; + } + + public Class getElementClass() { + return elementClass; } public abstract E at(int i); diff --git a/src/studio/kdb/KTableModel.java b/src/studio/kdb/KTableModel.java index 89b39e36..e632f646 100755 --- a/src/studio/kdb/KTableModel.java +++ b/src/studio/kdb/KTableModel.java @@ -89,6 +89,10 @@ public boolean isSortedDesc(int column) { public Class getColumnClass(int col) { return getColumn(col).getClass(); } + public Class getColumnElementClass(int col) { + return getColumn(col).getElementClass(); + } + //@TODO: add separate method which return K.KBase public Object getValueAt(int row,int col) { K.KBaseVector v = getColumn(col); diff --git a/src/studio/kdb/Session.java b/src/studio/kdb/Session.java index 8c8742aa..2b5e7a36 100644 --- a/src/studio/kdb/Session.java +++ b/src/studio/kdb/Session.java @@ -142,7 +142,7 @@ public void validate() { K.KTimestamp created = kConn.getStats().getLastConnectedTime(); if (created.isNull()) return; - K.KTimespan duration = K.KTimespan.period(created, K.KTimestamp.now()); + K.KTimespan duration = created.span(K.KTimestamp.now()); if (duration.toLong() > hours * HOUR_NS) { log.info("Closing session to stale server: " + server.getDescription(true)); kConn.close(); diff --git a/src/studio/ui/ExcelExporter.java b/src/studio/ui/ExcelExporter.java index 514de1dd..804e362d 100755 --- a/src/studio/ui/ExcelExporter.java +++ b/src/studio/ui/ExcelExporter.java @@ -103,7 +103,7 @@ public static Workbook buildWorkbook(TableModel model, ProgressMonitor pm) { cell.setCellValue(sd("HH:mm:ss.SSS", ((K.KTime) b).toTime())); } else if (columnClass == K.KTimestampVector.class) { char[] cs = sd("yyyy-MM-dd HH:mm:ss.SSS", - ((K.KTimestamp) b).toTimestamp()).toCharArray(); + ((K.KTimestamp) b).toJavaTimestamp()).toCharArray(); cs[10] = 'T'; cell.setCellValue(new String(cs)); } else if (columnClass == K.KMonthVector.class) { diff --git a/src/studio/ui/chart/Chart.java b/src/studio/ui/chart/Chart.java index ea56b226..10ca1b32 100755 --- a/src/studio/ui/chart/Chart.java +++ b/src/studio/ui/chart/Chart.java @@ -63,20 +63,20 @@ public class Chart implements ComponentListener { static { supportedClasses.addAll(Arrays.asList( - K.KIntVector.class, - K.KDoubleVector.class, - K.KFloatVector.class, - K.KShortVector.class, - K.KLongVector.class, - - K.KDateVector.class, - K.KTimeVector.class, - K.KTimestampVector.class, - K.KTimespanVector.class, - K.KDatetimeVector.class, - K.KMonthVector.class, - K.KSecondVector.class, - K.KMinuteVector.class) ); + K.KInteger.class, + K.KDouble.class, + K.KFloat.class, + K.KShort.class, + K.KLong.class, + + K.KDate.class, + K.KTime.class, + K.KTimestamp.class, + K.KTimespan.class, + K.KDatetime.class, + K.Month.class, + K.Second.class, + K.Minute.class) ); } private static StandardChartTheme currentTheme = new StandardChartTheme("JFree"); @@ -94,7 +94,7 @@ public Chart(KTableModel table) { private void initComponents() { List namesList = new ArrayList<>(); for (int index = 0; index < table.getColumnCount(); index++) { - Class clazz = table.getColumnClass(index); + Class clazz = table.getColumnElementClass(index); if (supportedClasses.contains(clazz)) { indexes.add(index); namesList.add(table.getColumnName(index)); @@ -255,7 +255,7 @@ public void refreshPlot() { } int xIndex = indexes.get(pnlConfig.getDomainIndex()); - Class xClazz = table.getColumnClass(xIndex); + Class xClazz = table.getColumnElementClass(xIndex); if (this.xIndex != xIndex) { NumberAxis xAxis = new NumberAxis(""); @@ -276,7 +276,7 @@ public void refreshPlot() { if (yIndex == xIndex) continue;; if (yClazz == null) { - yClazz = table.getColumnClass(yIndex); + yClazz = table.getColumnElementClass(yIndex); if (this.yIndex != yIndex) { NumberAxis yAxis = new NumberAxis(""); yAxis.setNumberFormatOverride(new KFormat(yClazz)); diff --git a/src/studio/ui/chart/KFormat.java b/src/studio/ui/chart/KFormat.java index dbf35355..125a747d 100644 --- a/src/studio/ui/chart/KFormat.java +++ b/src/studio/ui/chart/KFormat.java @@ -10,12 +10,12 @@ public class KFormat extends NumberFormat { - private Class kVectorClass; + private Class kClass; private static final DecimalFormat fractionFormat = new DecimalFormat("+0.#####;-0.#####"); - public KFormat(Class kVectorClass) { - this.kVectorClass = kVectorClass; + public KFormat(Class kClass) { + this.kClass = kClass; } @Override @@ -32,32 +32,32 @@ public Number parse(String source, ParsePosition parsePosition) { public StringBuffer format(double value, StringBuffer toAppendTo, FieldPosition pos) { boolean addFraction = true; K.KBase kValue; - if (kVectorClass == K.KIntVector.class || - kVectorClass == K.KDoubleVector.class || - kVectorClass == K.KFloatVector.class || - kVectorClass == K.KShortVector.class || - kVectorClass == K.KLongVector.class) { + if (kClass == K.KInteger.class || + kClass == K.KDouble.class || + kClass == K.KFloat.class || + kClass == K.KShort.class || + kClass == K.KLong.class) { kValue = new K.KDouble(value); addFraction = false; - } else if (kVectorClass == K.KDatetimeVector.class) { + } else if (kClass == K.KDatetime.class) { kValue = new K.KDatetime(value); addFraction = false; - } else if (kVectorClass == K.KDateVector.class) { + } else if (kClass == K.KDate.class) { kValue = new K.KDate(getInt(value)); - } else if (kVectorClass == K.KTimeVector.class) { + } else if (kClass == K.KTime.class) { kValue = new K.KTime(getInt(value)); - } else if (kVectorClass == K.KTimestampVector.class) { + } else if (kClass == K.KTimestamp.class) { kValue = new K.KTimestamp(getLong(value)); - } else if (kVectorClass == K.KTimespanVector.class) { + } else if (kClass == K.KTimespan.class) { kValue = new K.KTimespan(getLong(value)); - } else if (kVectorClass == K.KMonthVector.class) { + } else if (kClass == K.Month.class) { kValue = new K.Month(getInt(value)); - } else if (kVectorClass == K.KSecondVector.class) { + } else if (kClass == K.Second.class) { kValue = new K.Second(getInt(value)); - } else if (kVectorClass == K.KMinuteVector.class) { + } else if (kClass == K.Minute.class) { kValue = new K.Minute(getInt(value)); } else { - throw new IllegalArgumentException("Unsupported class: " + kVectorClass); + throw new IllegalArgumentException("Unsupported class: " + kClass); } toAppendTo.append(kValue.toString(KFormatContext.NO_TYPE)); diff --git a/test/studio/kdb/KTest.java b/test/studio/kdb/KTest.java index fd701b59..2c60afc1 100644 --- a/test/studio/kdb/KTest.java +++ b/test/studio/kdb/KTest.java @@ -408,12 +408,29 @@ public void testTimespanPeriod() { K.KTimestamp t1 = K.KTimestamp.now(c1); K.KTimestamp t2 = K.KTimestamp.now(c2); - K.KTimespan k = K.KTimespan.period(t1, t2); + K.KTimespan k = t1.span(t2); assertEquals( "1D01:08:05.864000000", k.toString() ); } + @Test + public void testDateToTimestamp() { + K.KDate date = new K.KDate(9092); + assertEquals("2024.11.22", date.toString()); + + K.KTimestamp t = new K.KTimestamp(785548800000000000L); + assertEquals("2024.11.22D00:00:00.000000000", t.toString()); + + assertEquals(date.toTimestamp(),t); + } + + + @Test + public void testElementClass() { + K.KList list = new K.KList(new K.KInteger(10), K.KInteger.ZERO); + assertEquals(K.KBase.class, list.getElementClass()); + } } diff --git a/test/studio/ui/ExcelExporterTest.java b/test/studio/ui/ExcelExporterTest.java new file mode 100644 index 00000000..9881bcfa --- /dev/null +++ b/test/studio/ui/ExcelExporterTest.java @@ -0,0 +1,23 @@ +package studio.ui; + +import org.apache.poi.ss.usermodel.Workbook; +import org.junit.jupiter.api.Test; +import studio.kdb.K; +import studio.kdb.ListModel; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ExcelExporterTest { + + private void check(String expected, K.KBaseVector list) { + ListModel model = new ListModel(list); + Workbook w = ExcelExporter.buildWorkbook(model, null); + assertEquals(expected, w.getSheetAt(0).getRow(1).getCell(0).toString()); + } + + @Test + public void timestampExportTest() { + check("2003-11-29T21:33:09.012", new K.KTimestampVector(123456789012345678L)); + check("", new K.KTimestampVector(Long.MIN_VALUE)); + } +}