├── .github
└── workflows
│ └── maven-verify.yml
├── .gitignore
├── LICENSE
├── README.md
├── RELEASE_NOTES.md
├── checkstyle-configuration.xml
├── docs
├── CSV_FILE_SUPPORT.md
├── NULL_SUPPORT.md
├── POOLING.md
├── data_frame_no_pooling.png
└── data_frame_with_pooling.png
├── pom.xml
└── src
├── main
├── antlr4
│ └── io
│ │ └── github
│ │ └── vmzakharov
│ │ └── ecdataframe
│ │ └── grammar
│ │ └── ModelScript.g4
└── java
│ └── io
│ └── github
│ └── vmzakharov
│ └── ecdataframe
│ ├── dataframe
│ ├── AggregateFunction.java
│ ├── DataFrame.java
│ ├── DfBooleanColumn.java
│ ├── DfBooleanColumnComputed.java
│ ├── DfBooleanColumnStored.java
│ ├── DfCellComparator.java
│ ├── DfColumn.java
│ ├── DfColumnAbstract.java
│ ├── DfColumnComputed.java
│ ├── DfColumnSortOrder.java
│ ├── DfColumnStored.java
│ ├── DfCursor.java
│ ├── DfDateColumn.java
│ ├── DfDateColumnComputed.java
│ ├── DfDateColumnStored.java
│ ├── DfDateTimeColumn.java
│ ├── DfDateTimeColumnComputed.java
│ ├── DfDateTimeColumnStored.java
│ ├── DfDecimalColumn.java
│ ├── DfDecimalColumnComputed.java
│ ├── DfDecimalColumnStored.java
│ ├── DfDoubleColumn.java
│ ├── DfDoubleColumnComputed.java
│ ├── DfDoubleColumnStored.java
│ ├── DfFloatColumn.java
│ ├── DfFloatColumnComputed.java
│ ├── DfFloatColumnStored.java
│ ├── DfIndex.java
│ ├── DfIndexKeeper.java
│ ├── DfIntColumn.java
│ ├── DfIntColumnComputed.java
│ ├── DfIntColumnStored.java
│ ├── DfIterate.java
│ ├── DfJoin.java
│ ├── DfLongColumn.java
│ ├── DfLongColumnComputed.java
│ ├── DfLongColumnStored.java
│ ├── DfObjectColumn.java
│ ├── DfObjectColumnAbstract.java
│ ├── DfObjectColumnComputed.java
│ ├── DfObjectColumnStored.java
│ ├── DfStringColumn.java
│ ├── DfStringColumnComputed.java
│ ├── DfStringColumnStored.java
│ ├── DfTuple.java
│ ├── aggregation
│ │ ├── Avg.java
│ │ ├── Avg2d.java
│ │ ├── Count.java
│ │ ├── Max.java
│ │ ├── Min.java
│ │ ├── Same.java
│ │ └── Sum.java
│ ├── compare
│ │ ├── BooleanComparisonResult.java
│ │ ├── ComparisonResult.java
│ │ ├── DateComparisonResult.java
│ │ ├── DateTimeComparisonResult.java
│ │ ├── DecimalComparisonResult.java
│ │ ├── DoubleComparisonResult.java
│ │ ├── LongComparisonResult.java
│ │ ├── ObjectComparisonResult.java
│ │ └── StringComparisonResult.java
│ └── util
│ │ ├── DataFrameCompare.java
│ │ └── DataFramePrettyPrint.java
│ ├── dataset
│ ├── BooleanFormatter.java
│ ├── BooleanSchemaColumn.java
│ ├── CsvDataSet.java
│ ├── CsvSchema.java
│ ├── CsvSchemaColumn.java
│ ├── DataSet.java
│ ├── DataSetAbstract.java
│ ├── DateSchemaColumn.java
│ ├── DateTimeSchemaColumn.java
│ ├── DecimalFormatter.java
│ ├── DecimalSchemaColumn.java
│ ├── DoubleFormatter.java
│ ├── DoubleSchemaColumn.java
│ ├── FloatFormatter.java
│ ├── FloatSchemaColumn.java
│ ├── HierarchicalDataSet.java
│ ├── IntFormatter.java
│ ├── IntSchemaColumn.java
│ ├── LongFormatter.java
│ ├── LongSchemaColumn.java
│ ├── ObjectListDataSet.java
│ └── StringSchemaColumn.java
│ ├── dsl
│ ├── AbstractScript.java
│ ├── AliasExpr.java
│ ├── AnonymousScript.java
│ ├── ArithmeticOp.java
│ ├── AssignExpr.java
│ ├── BinaryExpr.java
│ ├── BinaryOp.java
│ ├── BooleanOp.java
│ ├── ComparisonOp.java
│ ├── ContainsOp.java
│ ├── DecimalExpr.java
│ ├── EvalContext.java
│ ├── EvalContextAbstract.java
│ ├── Expression.java
│ ├── FunctionCallExpr.java
│ ├── FunctionDescriptor.java
│ ├── FunctionScript.java
│ ├── IfElseExpr.java
│ ├── IndexExpr.java
│ ├── PredicateOp.java
│ ├── ProjectionExpr.java
│ ├── PropertyPathExpr.java
│ ├── Script.java
│ ├── SimpleEvalContext.java
│ ├── StatementSequenceScript.java
│ ├── UnaryExpr.java
│ ├── UnaryOp.java
│ ├── VarExpr.java
│ ├── VectorExpr.java
│ ├── function
│ │ ├── BuiltInFunctions.java
│ │ ├── IntrinsicFunctionDescriptor.java
│ │ └── IntrinsicFunctionDescriptorBuilder.java
│ ├── value
│ │ ├── BooleanValue.java
│ │ ├── DataFrameValue.java
│ │ ├── DateTimeValue.java
│ │ ├── DateValue.java
│ │ ├── DecimalValue.java
│ │ ├── DoubleValue.java
│ │ ├── FloatValue.java
│ │ ├── IntValue.java
│ │ ├── LongValue.java
│ │ ├── NumberValue.java
│ │ ├── RealNumberValue.java
│ │ ├── StringValue.java
│ │ ├── Value.java
│ │ ├── ValueType.java
│ │ ├── VectorValue.java
│ │ └── WholeNumberValue.java
│ └── visitor
│ │ ├── ExpressionEvaluationVisitor.java
│ │ ├── ExpressionVisitor.java
│ │ ├── InMemoryEvaluationVisitor.java
│ │ ├── PrettyPrintVisitor.java
│ │ └── TypeInferenceVisitor.java
│ ├── grammar
│ ├── CollectingErrorListener.java
│ └── ModelScriptTreeBuilderVisitor.java
│ └── util
│ ├── CollectingPrinter.java
│ ├── ConfigureMessages.java
│ ├── ExceptionFactory.java
│ ├── ExpressionParserHelper.java
│ ├── FormatWithPlaceholders.java
│ ├── Printer.java
│ ├── PrinterFactory.java
│ ├── Stopwatch.java
│ ├── SysErrPrinter.java
│ └── SysOutPrinter.java
└── test
├── java
└── io
│ └── github
│ └── vmzakharov
│ └── ecdataframe
│ ├── AggregateFunctionTest.java
│ ├── DateExpressionTest.java
│ ├── ExpressionFloatValueTest.java
│ ├── ExpressionIntValueTest.java
│ ├── ExpressionTestUtil.java
│ ├── ExpressionWithNullValuesTest.java
│ ├── FunctionDeclarationsTest.java
│ ├── HandcraftedExpressionTreeTest.java
│ ├── ImmutableVariablesTest.java
│ ├── IsEmptyOperationTest.java
│ ├── ParserErrorReportingTest.java
│ ├── ScriptFromStringTest.java
│ ├── SimpleExpressionParsingTest.java
│ ├── StandaloneExpressionFromStringTest.java
│ ├── TypeInferenceForBuiltInFunctionsTest.java
│ ├── TypeInferenceTest.java
│ ├── TypeInferenceUtil.java
│ ├── VectorExpressionTest.java
│ ├── dataframe
│ ├── BasicDataFrameTest.java
│ ├── ColumnIteratorTest.java
│ ├── DataFrameAddColumnWithDataTest.java
│ ├── DataFrameAggregationAvg2dTest.java
│ ├── DataFrameAggregationErrorMessageTest.java
│ ├── DataFrameAggregationNoGroupingTest.java
│ ├── DataFrameAggregationNullsAreOkayTest.java
│ ├── DataFrameAggregationNullsArePoisonousTest.java
│ ├── DataFrameAggregationSameTest.java
│ ├── DataFrameAggregationTest.java
│ ├── DataFrameAggregationWithCustomFunctionsTest.java
│ ├── DataFrameAggregationWithGroupByTest.java
│ ├── DataFrameAggregationWithIndexTest.java
│ ├── DataFrameBitmapTest.java
│ ├── DataFrameBooleanColumnTest.java
│ ├── DataFrameComputedColumnsFailureTest.java
│ ├── DataFrameComputedColumnsTest.java
│ ├── DataFrameComputedWithInferredTypeTest.java
│ ├── DataFrameComputedWithNullsTest.java
│ ├── DataFrameCopyTest.java
│ ├── DataFrameDistinctTest.java
│ ├── DataFrameExpressionTest.java
│ ├── DataFrameFilterTest.java
│ ├── DataFrameIndexTest.java
│ ├── DataFrameIterateTest.java
│ ├── DataFrameJoinTest.java
│ ├── DataFrameLookupJoinTest.java
│ ├── DataFramePivotColumnSortTest.java
│ ├── DataFramePivotTest.java
│ ├── DataFramePoolingTest.java
│ ├── DataFrameSortDirectionTest.java
│ ├── DataFrameSortTest.java
│ ├── DataFrameToStringTest.java
│ ├── DataFrameUnionTest.java
│ ├── DataFrameUtil.java
│ ├── DataFrameWithDecimalColumnTest.java
│ ├── DfColumnCompareTest.java
│ ├── IntersectionAndDifferencesTest.java
│ ├── TupleCompareTest.java
│ ├── bench
│ │ └── DataFrameParallelTest.java
│ └── util
│ │ ├── DataFrameCompareTest.java
│ │ └── DataFramePrettyPrintTest.java
│ ├── dataset
│ ├── CsvCodeScratchpad.java
│ ├── DataFrameLoadBooleanTest.java
│ ├── DataFrameLoadFromZippedTest.java
│ ├── DataFrameLoadTest.java
│ ├── DataFrameWriteBooleanTest.java
│ ├── DataFrameWriteTest.java
│ ├── FormattedColumnsTest.java
│ ├── SeparatedTextSplittingTest.java
│ └── StringBasedCsvDataSet.java
│ ├── dsl
│ ├── DecimalExpressionTest.java
│ ├── ObjectValueCompareOpTest.java
│ ├── ObjectValueContainsOpTest.java
│ ├── PrettyPrintingTest.java
│ ├── ValueCompareTest.java
│ ├── function
│ │ ├── BuiltInFormatterTest.java
│ │ ├── BuiltInFunctionTest.java
│ │ └── RuntimeAddedFunctionTest.java
│ ├── projection
│ │ ├── Donut.java
│ │ ├── HierarchicalDataSetProjectionTest.java
│ │ ├── Person.java
│ │ └── ProjectionExtraTypesTest.java
│ └── value
│ │ └── ValueTest.java
│ └── util
│ ├── ExceptionFactoryTest.java
│ └── FormatWithPlaceholderTest.java
└── resources
├── Messages.properties
└── employees.csv
/.github/workflows/maven-verify.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
3 |
4 | name: Maven Verify Phase
5 |
6 | on: [push, pull_request]
7 |
8 | jobs:
9 | build:
10 |
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - uses: actions/checkout@v4
15 | - name: Set up JDK 17
16 | uses: actions/setup-java@v4
17 | with:
18 | java-version: '17'
19 | distribution: 'temurin'
20 | cache: maven
21 | - name: Run Maven Verify Phase
22 | run: mvn --batch-mode verify --file pom.xml
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
25 | #intelliJ
26 | .idea
27 | *.iml
28 | *.ipr
29 |
30 | #maven
31 | target/
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Vladimir Zakharov
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/docs/POOLING.md:
--------------------------------------------------------------------------------
1 | # Pooling
2 |
3 | ## Introduction
4 |
5 | Data Frame instances support (optional) **pooling** of object values. Pooling means that as an object is added to the data frame, it is first looked up in the pool and if an equal object is found, that reference is used. If an equal object is not found, the new object is added to the pool. In other words, with pooling for objects that are equal the memory needs to be allocated for only one instance.
6 |
7 | A pool is scoped for a column.
8 |
9 | For columns with a lot of repeating values pooling can result in substantial memory savings and, in certain scenarios, in performance improvements.
10 |
11 | ### Example
12 | Let's say there is a data frame storing customer orders. There are three columns: customer name (string), order number (integer), order date (date).
13 |
14 | There are 10 rows in the data frame.
15 |
16 | Without pooling there are 10 instances of string objects and 10 instances of date objects.
17 |
18 | 
19 |
20 | With pooling, there are 4 instances of strings and 3 instances of dates. By Grabthar's Hammer... what a savings.
21 |
22 | 
23 |
24 | ## Managing Pooling
25 |
26 | ### Enabling and Disabling
27 |
28 | Pooling can be enabled and disabled at the data frame or at the individual column level.
29 |
30 | To enabling pooling at the data frame level, call `enablePooling()` on a data frame instance, for example
31 |
32 | ```java
33 | DataFrame df = new DataFrame("Data Frame");
34 | df.enablePooling();
35 | // ...populate data frame...
36 | ```
37 |
38 | This method will enable pooling on all data frame columns (specifically, object columns, as there is no pooling of primitive values, so enabling pooling on primitive columns does nothing.)
39 |
40 | To enable pooling for a specific column call `enablePooling()` on this column, for example
41 | ```java
42 | DataFrame df = new DataFrame("Data Frame");
43 | df.getColumnNamed("name").enablePooling();
44 | // ...populate data frame...
45 | ```
46 |
47 | Calling `enablePooling()` on a data frame (or a column) with data will cause the necessary pools to be rebuilt, and the data repopulated, potentially resulting in memory compression at the cost of this extra work.
48 |
49 | To disable pooling call `disablePooling()` on either a data frame instance or a column instance, depending on the desired scope.
50 |
51 | Note that calling `seal()` method (indicating that the dataframe construction is complete) will in turn call `disablePooling()`.
52 |
53 | ### Data Frame Transformation and Pooling
54 |
55 | By default, the data frames created as a result of extracting data from an existing data frame (using methods such as `select`, `reject`, `partition`) will retain the pooling setting of the source data frame.
56 |
57 | Note that if the source data frame was created with pooling enabled, regardless of its current pooling status, the derived data frames will benefit from that. That is, the total number of value instances will not increase as no new instances will be created. So you only need pooling on derived data frames if you are planning to add data to them.
58 |
59 | If the source data frame has pooling enabled, and you do not need pooling for a derived data frame as you are not planning to add any data to it, call `disablePooling` on it to avoid the overhead of having an active pool.
60 |
--------------------------------------------------------------------------------
/docs/data_frame_no_pooling.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmzakharov/dataframe-ec/8167010ceab19aff28a62a477d61dce9217fd4f2/docs/data_frame_no_pooling.png
--------------------------------------------------------------------------------
/docs/data_frame_with_pooling.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vmzakharov/dataframe-ec/8167010ceab19aff28a62a477d61dce9217fd4f2/docs/data_frame_with_pooling.png
--------------------------------------------------------------------------------
/src/main/antlr4/io/github/vmzakharov/ecdataframe/grammar/ModelScript.g4:
--------------------------------------------------------------------------------
1 | grammar ModelScript;
2 |
3 | script :
4 | functionDeclarationExpr*
5 | statementSequence
6 | projectionStatement?
7 | ;
8 |
9 | functionDeclarationExpr :
10 | 'function' ID ('(' idList ')' | '(' ')')?
11 | '{'
12 | statementSequence
13 | '}'
14 | ;
15 |
16 | statementSequence: statement*;
17 |
18 | statement :
19 | ID '=' expr #assignExpr
20 | | IF expr
21 | THEN ifBody=statementSequence
22 | (ELSE elseBody=statementSequence)?
23 | ENDIF #conditionExpr
24 | | expr #freeExp
25 | ;
26 |
27 | projectionStatement :
28 | 'project' '{' exprList '}' ('where' expr)?
29 | ;
30 |
31 | expr :
32 | ID ( '.' ID)+? #propertyPathExpr
33 | | ID ':' expr #aliasExpr
34 | | ID ('(' exprList ')' | '(' ')') #functionCallExpr
35 | | '(' expr ')' #parenExpr
36 | | '-' expr #unaryMinusExpr
37 | | expr IS_NOT_EMPTY #isNotEmptyExpr
38 | | expr IS_EMPTY #isEmptyExpr
39 | | expr IS_NOT_NULL #isNotNullExpr
40 | | expr IS_NULL #isNullExpr
41 | | NOT expr #notExpr
42 | | expr '[' expr ']' #indexVectorExpr
43 | | expr op=(MUL | DIV) expr #mulDivExpr
44 | | expr op=(ADD | SUB) expr #addSubExpr
45 | | expr op=(GT | GTE | LT | LTE | EQ | NE) expr #compareExpr
46 | | expr (NOT_IN | IN) expr #inExpr
47 | | expr op=AND expr #andExpr
48 | | expr op=(OR | XOR) expr #orExpr
49 | | vectorExpr #standaloneVectorExpr
50 | | INT #intLiteralExpr
51 | | DOUBLE #doubleLiteralExpr
52 | | STRING #stringLiteralExpr
53 | | ID #varExpr
54 | | condExpr=expr '?' ifExpr=expr ':' elseExpr=expr #ternaryExpr
55 | ;
56 |
57 | vectorExpr : '(' exprList ')' | '(' ')';
58 |
59 | exprList : expr ( ',' expr )*;
60 |
61 | idList : ID ( ',' ID) *;
62 |
63 | MUL : '*' ;
64 | DIV : '/' ;
65 | ADD : '+' ;
66 | SUB : '-' ;
67 |
68 | GT : '>' ;
69 | GTE : '>=' ;
70 | LT : '<' ;
71 | LTE : '<=' ;
72 | EQ : '==';
73 | NE : '!=';
74 |
75 | NOT_IN : 'not in' | 'NOT IN' ;
76 | IN : 'in' | 'IN' ;
77 | IS_EMPTY : 'is empty' | 'IS EMPTY' ;
78 | IS_NOT_EMPTY : 'is not empty' | 'IS NOT EMPTY' ;
79 | IS_NULL : 'is null' | 'IS NULL' ;
80 | IS_NOT_NULL : 'is not null' | 'IS NOT NULL' ;
81 |
82 | AND : 'and' | 'AND';
83 | OR : 'or' | 'OR';
84 | XOR : 'xor' | 'XOR';
85 |
86 | NOT : 'not' | 'NOT' | '!';
87 |
88 | IF : 'if' | 'IF';
89 | THEN : 'then' | 'THEN';
90 | ELSE : 'else' | 'ELSE';
91 | ENDIF : 'endif' | 'ENDIF';
92 |
93 | ID : '${' .*? '}' | LETTER (LETTER|DIGIT)* ;
94 | INT : DIGIT+;
95 | DOUBLE : ('.' DIGIT+ | DIGIT+ ('.' DIGIT*)? ) ;
96 | LINE_COMMENT : '//' ~[\r\n]* -> skip;
97 | WS : [ \t]+ -> skip;
98 | NL : [\n\r] -> skip;
99 | STRING : '"' ( ESC | . )*? '"' | '\'' ( ESC | . )*? '\'';
100 |
101 | fragment
102 | ESC : '\\' [btnr"\\];
103 | LETTER : [a-zA-Z\u0080-\u00FF_];
104 | DIGIT : [0-9];
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfBooleanColumnComputed.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.Expression;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.BooleanValue;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
6 | import io.github.vmzakharov.ecdataframe.util.ExpressionParserHelper;
7 |
8 | public class DfBooleanColumnComputed
9 | extends DfBooleanColumn
10 | implements DfColumnComputed
11 | {
12 | private final String expressionAsString;
13 | private final Expression expression;
14 |
15 | public DfBooleanColumnComputed(DataFrame newDataFrame, String newName, String newExpressionAsString)
16 | {
17 | super(newDataFrame, newName);
18 | this.expressionAsString = newExpressionAsString;
19 | this.expression = ExpressionParserHelper.DEFAULT.toExpressionOrScript(this.expressionAsString);
20 | }
21 |
22 | @Override
23 | public boolean getBoolean(int rowIndex)
24 | {
25 | Value result = this.getValue(rowIndex);
26 |
27 | if (result.isVoid())
28 | {
29 | throw new NullPointerException("Null value at " + this.getName() + "[" + rowIndex + "]");
30 | }
31 |
32 | return ((BooleanValue) result).isTrue();
33 | }
34 |
35 | @Override
36 | public Object getObject(int rowIndex)
37 | {
38 | Value result = this.getValue(rowIndex);
39 |
40 | return result.isVoid() ? null : ((BooleanValue) result).isTrue();
41 | }
42 |
43 | @Override
44 | public boolean isNull(int rowIndex)
45 | {
46 | return this.getObject(rowIndex) == null;
47 | }
48 |
49 | @Override
50 | protected void addAllItemsFrom(DfBooleanColumn booleanColumn)
51 | {
52 | this.throwUnmodifiableColumnException();
53 | }
54 |
55 | @Override
56 | public int getSize()
57 | {
58 | return this.getDataFrame().rowCount();
59 | }
60 |
61 | @Override
62 | public String getExpressionAsString()
63 | {
64 | return this.expressionAsString;
65 | }
66 |
67 | @Override
68 | public Expression getExpression()
69 | {
70 | return this.expression;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfCellComparator.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.compare.ComparisonResult;
4 |
5 | public interface DfCellComparator
6 | {
7 | ComparisonResult compare(int thisRowIndex, int otherRowIndex);
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
5 |
6 | import static io.github.vmzakharov.ecdataframe.util.ExceptionFactory.exceptionByKey;
7 |
8 | public interface DfColumn
9 | {
10 | String getName();
11 |
12 | String getValueAsString(int rowIndex);
13 |
14 | default String getValueAsStringLiteral(int rowIndex)
15 | {
16 | return this.isNull(rowIndex) ? "" : this.getValueAsString(rowIndex);
17 | }
18 |
19 | void addObject(Object newObject);
20 |
21 | void addValue(Value value);
22 |
23 | boolean isNull(int rowIndex);
24 |
25 | Object getObject(int rowIndex);
26 |
27 | DataFrame getDataFrame();
28 |
29 | Value getValue(int rowIndex);
30 |
31 | ValueType getType();
32 |
33 | boolean isStored();
34 |
35 | default boolean isComputed()
36 | {
37 | return !this.isStored();
38 | }
39 |
40 | int getSize();
41 |
42 | void setObject(int rowIndex, Object anObject);
43 |
44 | void addEmptyValue();
45 |
46 | default Object aggregate(AggregateFunction aggregateFunction)
47 | {
48 | if (!aggregateFunction.supportsSourceType(this.getType()))
49 | {
50 | throw aggregateFunction.notApplicable(this);
51 | }
52 |
53 | if (this.getSize() == 0)
54 | {
55 | return aggregateFunction.valueForEmptyColumn(this);
56 | }
57 |
58 | try
59 | {
60 | return aggregateFunction.applyToColumn(this);
61 | }
62 | catch (NullPointerException npe)
63 | {
64 | // npe can be thrown if there is a null value stored in a column of primitive type, this can happen when
65 | // converting column values to a list.
66 | return null;
67 | }
68 | }
69 |
70 | void applyAggregator(int targetRowIndex, DfColumn sourceColumn, int sourceRowIndex, AggregateFunction aggregateFunction);
71 |
72 | DfColumn cloneSchemaAndAttachTo(DataFrame attachTo);
73 |
74 | DfColumn cloneSchemaAndAttachTo(DataFrame attachTo, String newName);
75 |
76 | void addRowToColumn(int rowIndex, DfColumn target);
77 |
78 | default void enablePooling()
79 | {
80 | // nothing
81 | }
82 |
83 | default void disablePooling()
84 | {
85 | // nothing
86 | }
87 |
88 | DfColumn mergeWithInto(DfColumn other, DataFrame target);
89 |
90 | DfColumn copyTo(DataFrame target);
91 |
92 | default DfCellComparator columnComparator(DfColumn otherColumn)
93 | {
94 | throw exceptionByKey("DF_NO_COL_COMPARATOR")
95 | .with("columnName", this.getName())
96 | .with("columnType", this.getType())
97 | .getUnsupported();
98 | }
99 |
100 | default int dataFrameRowIndex(int virtualRowIndex)
101 | {
102 | return this.getDataFrame().rowIndexMap(virtualRowIndex);
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfColumnAbstract.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 |
5 | import static io.github.vmzakharov.ecdataframe.util.ExceptionFactory.exceptionByKey;
6 |
7 | public abstract class DfColumnAbstract
8 | implements DfColumn
9 | {
10 | final private String name;
11 |
12 | private DataFrame dataFrame;
13 |
14 | public DfColumnAbstract(DataFrame newDataFrame, String newName)
15 | {
16 | this.dataFrame = newDataFrame;
17 | this.name = newName;
18 | }
19 |
20 | @Override
21 | public String getName()
22 | {
23 | return this.name;
24 | }
25 |
26 | @Override
27 | public DataFrame getDataFrame()
28 | {
29 | return this.dataFrame;
30 | }
31 |
32 | public void setDataFrame(DataFrame newDataFrame)
33 | {
34 | if (this.dataFrame != null)
35 | {
36 | exceptionByKey("DF_COL_ALREADY_LINKED").with("columnName", this.getName()).fire();
37 | }
38 |
39 | this.dataFrame = newDataFrame;
40 | }
41 |
42 | @Override
43 | public DfColumn cloneSchemaAndAttachTo(DataFrame attachTo)
44 | {
45 | return this.cloneSchemaAndAttachTo(attachTo, this.getName());
46 | }
47 |
48 | @Override
49 | public DfColumn cloneSchemaAndAttachTo(DataFrame attachTo, String newName)
50 | {
51 | return this.isStored()
52 | ?
53 | attachTo.newColumn(newName, this.getType())
54 | :
55 | attachTo.newColumn(newName, this.getType(), ((DfColumnComputed) this).getExpressionAsString());
56 | }
57 |
58 | protected DfColumn validateAndCreateTargetColumn(DfColumn other, DataFrame target)
59 | {
60 | if (!this.getType().equals(other.getType()))
61 | {
62 | exceptionByKey("DF_MERGE_COL_DIFF_TYPES")
63 | .with("firstColumnName", this.getName())
64 | .with("firstColumnType", this.getType())
65 | .with("secondColumnName", other.getName())
66 | .with("secondColumnType", other.getType())
67 | .fire();
68 | }
69 |
70 | DfColumnStored newColumn = target.newColumn(this.getName(), this.getType());
71 |
72 | newColumn.ensureInitialCapacity(this.getSize() + other.getSize());
73 |
74 | return newColumn;
75 | }
76 |
77 | protected DfColumn copyColumnSchemaAndEnsureCapacity(DataFrame target)
78 | {
79 | DfColumnStored newColumn = target.newColumn(this.getName(), this.getType());
80 |
81 | newColumn.ensureInitialCapacity(this.getSize());
82 |
83 | return newColumn;
84 | }
85 |
86 | protected void throwAddingIncompatibleValueException(Value value)
87 | {
88 | exceptionByKey("DF_BAD_VAL_ADD_TO_COL")
89 | .with("valueType", value.getType())
90 | .with("columnName", this.getName())
91 | .with("columnType", this.getType())
92 | .with("value", value.asStringLiteral())
93 | .fire();
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfColumnComputed.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.Expression;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
5 |
6 | import static io.github.vmzakharov.ecdataframe.util.ExceptionFactory.exceptionByKey;
7 |
8 | public interface DfColumnComputed
9 | extends DfColumn
10 | {
11 | @Override
12 | default boolean isStored()
13 | {
14 | return false;
15 | }
16 |
17 | String getExpressionAsString();
18 |
19 | Expression getExpression();
20 |
21 | @Override
22 | default void setObject(int rowIndex, Object anObject)
23 | {
24 | exceptionByKey("DF_SET_VAL_ON_COMP_COL").with("columnName", this.getName()).fire();
25 | }
26 |
27 | @Override
28 | default Value getValue(int rowIndex)
29 | {
30 | this.getDataFrame().setEvalContextRowIndex(rowIndex);
31 |
32 | return this.getExpression().evaluate(this.getDataFrame().getEvalVisitor());
33 | }
34 |
35 | @Override
36 | default void addEmptyValue()
37 | {
38 | // no-op
39 | }
40 |
41 | @Override
42 | default void addValue(Value value)
43 | {
44 | this.throwUnmodifiableColumnException();
45 | }
46 |
47 | /**
48 | * a placeholder method for computed columns defined so that {@code addRow()} could be called on a data frame with
49 | * computed columns. If any value other than {@code null} is passed the method throws an exception
50 | * @param newObject an object to add to the column, expected {@code null} for computed columns
51 | */
52 | @Override
53 | default void addObject(Object newObject)
54 | {
55 | if (newObject != null)
56 | {
57 | this.throwUnmodifiableColumnException();
58 | }
59 | }
60 |
61 | @Override
62 | default void applyAggregator(int targetRowIndex, DfColumn sourceColumn, int sourceRowIndex, AggregateFunction aggregateFunction)
63 | {
64 | exceptionByKey("DF_AGG_VAL_TO_COMP_COL").with("columnNane", this.getName()).fire();
65 | }
66 |
67 | default void throwUnmodifiableColumnException()
68 | {
69 | throw exceptionByKey("DF_CALC_COL_MODIFICATION").with("columnNane", this.getName()).getUnsupported();
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfColumnSortOrder.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | public enum DfColumnSortOrder
4 | {
5 | ASC, DESC;
6 |
7 | public int order(int comparisonResult)
8 | {
9 | return this == DESC ? -comparisonResult : comparisonResult;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfColumnStored.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | public interface DfColumnStored
4 | extends DfColumn
5 | {
6 | @Override
7 | default boolean isStored()
8 | {
9 | return true;
10 | }
11 |
12 | void ensureInitialCapacity(int newCapacity);
13 |
14 | @Override
15 | default void applyAggregator(int targetRowIndex, DfColumn sourceColumn, int sourceRowIndex, AggregateFunction aggregator)
16 | {
17 | if (aggregator.nullsArePoisonous())
18 | {
19 | if (this.isNull(targetRowIndex))
20 | {
21 | return;
22 | }
23 |
24 | if (sourceColumn.isNull(sourceRowIndex))
25 | {
26 | this.setObject(targetRowIndex, null);
27 | return;
28 | }
29 | }
30 |
31 | this.aggregateValueInto(targetRowIndex, sourceColumn, sourceRowIndex, aggregator);
32 | }
33 |
34 | /**
35 | * protected - do not call, to be implemented by the subtypes
36 | * calls the provided aggregator on a value of sourceColumn
at sourceRowIndex
with the
37 | * combined with the current aggregated value at rowIndex
of this column
38 | *
39 | * @param rowIndex - the row index in this column at which to store the new aggregated value
40 | * @param sourceColumn - the column from which to extract the new value to be aggregated
41 | * @param sourceRowIndex - the row index of the new value to be aggregated
42 | * @param aggregator - the aggregate function to be applied to the existing aggregate value in this column and
43 | * the new value extracted from the sourceColumn
44 | */
45 | void aggregateValueInto(int rowIndex, DfColumn sourceColumn, int sourceRowIndex, AggregateFunction aggregator);
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfCursor.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import java.math.BigDecimal;
4 | import java.time.LocalDate;
5 | import java.time.LocalDateTime;
6 |
7 | public class DfCursor
8 | {
9 | private final DataFrame dataFrame;
10 | private int rowIndex;
11 |
12 | public DfCursor(DataFrame newDataFrame)
13 | {
14 | this.dataFrame = newDataFrame;
15 | }
16 |
17 | public String getString(String columnName)
18 | {
19 | return this.dataFrame.getString(columnName, this.rowIndex);
20 | }
21 |
22 | public long getLong(String columnName)
23 | {
24 | return this.dataFrame.getLong(columnName, this.rowIndex);
25 | }
26 |
27 | public long getInt(String columnName)
28 | {
29 | return this.dataFrame.getInt(columnName, this.rowIndex);
30 | }
31 |
32 | public double getDouble(String columnName)
33 | {
34 | return this.dataFrame.getDouble(columnName, this.rowIndex);
35 | }
36 |
37 | public float getFloat(String columnName)
38 | {
39 | return this.dataFrame.getFloat(columnName, this.rowIndex);
40 | }
41 |
42 | public boolean getBoolean(String columnName)
43 | {
44 | return this.dataFrame.getBoolean(columnName, this.rowIndex);
45 | }
46 |
47 | public BigDecimal getDecimal(String columnName)
48 | {
49 | return this.dataFrame.getDecimal(columnName, this.rowIndex);
50 | }
51 |
52 | public LocalDate getDate(String columnName)
53 | {
54 | return this.dataFrame.getDate(columnName, this.rowIndex);
55 | }
56 |
57 | public LocalDateTime getDateTime(String columnName)
58 | {
59 | return this.dataFrame.getDateTime(columnName, this.rowIndex);
60 | }
61 |
62 | public Object getObject(String columnName)
63 | {
64 | return this.dataFrame.getObject(columnName, this.rowIndex);
65 | }
66 |
67 | public int rowIndex()
68 | {
69 | return this.rowIndex;
70 | }
71 |
72 | public DfCursor rowIndex(int newRowIndex)
73 | {
74 | this.rowIndex = newRowIndex;
75 | return this;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfDateColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.compare.DateComparisonResult;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.DateValue;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
6 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
7 |
8 | import java.time.LocalDate;
9 | import java.time.format.DateTimeFormatter;
10 |
11 | public interface DfDateColumn
12 | extends DfObjectColumn
13 | {
14 | DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_DATE;
15 |
16 | @Override
17 | default String getValueAsString(int rowIndex)
18 | {
19 | LocalDate value = this.getTypedObject(rowIndex);
20 | return value == null ? "" : this.FORMATTER.format(value);
21 | }
22 |
23 | @Override
24 | default ValueType getType()
25 | {
26 | return ValueType.DATE;
27 | }
28 |
29 | @Override
30 | default Value objectToValue(LocalDate anObject)
31 | {
32 | return new DateValue(anObject);
33 | }
34 |
35 | @Override
36 | default void addRowToColumn(int rowIndex, DfColumn target)
37 | {
38 | ((DfDateColumnStored) target).addMyType(this.getTypedObject(rowIndex));
39 | }
40 |
41 | @Override
42 | default DfCellComparator columnComparator(DfColumn otherColumn)
43 | {
44 | DfDateColumn otherStringColumn = (DfDateColumn) otherColumn;
45 |
46 | return (thisRowIndex, otherRowIndex) -> new DateComparisonResult(
47 | this.getTypedObject(this.dataFrameRowIndex(thisRowIndex)),
48 | otherStringColumn.getTypedObject(otherStringColumn.dataFrameRowIndex(otherRowIndex)));
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfDateColumnComputed.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.DateValue;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
5 |
6 | import java.time.LocalDate;
7 |
8 | public class DfDateColumnComputed
9 | extends DfObjectColumnComputed
10 | implements DfDateColumn
11 | {
12 | public DfDateColumnComputed(DataFrame newDataFrame, String newName, String newExpressionAsString)
13 | {
14 | super(newDataFrame, newName, newExpressionAsString);
15 | }
16 |
17 | @Override
18 | public LocalDate getTypedObject(int rowIndex)
19 | {
20 | Value result = this.getValue(rowIndex);
21 |
22 | return result.isVoid() ? null : ((DateValue) result).dateValue();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfDateColumnStored.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.DateValue;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
5 | import org.eclipse.collections.api.list.ListIterable;
6 |
7 | import java.time.LocalDate;
8 |
9 | public class DfDateColumnStored
10 | extends DfObjectColumnStored
11 | implements DfDateColumn
12 | {
13 | public DfDateColumnStored(DataFrame owner, String newName)
14 | {
15 | super(owner, newName);
16 | }
17 |
18 | public DfDateColumnStored(DataFrame owner, String newName, ListIterable newValues)
19 | {
20 | super(owner, newName, newValues);
21 | }
22 |
23 | @Override
24 | public void addObject(Object newObject)
25 | {
26 | this.addMyType((LocalDate) newObject);
27 | }
28 |
29 | @Override
30 | public void addValue(Value value)
31 | {
32 | if (value.isVoid())
33 | {
34 | this.addObject(null);
35 | }
36 | else if (value.isDate())
37 | {
38 | this.addMyType(((DateValue) value).dateValue());
39 | }
40 | else
41 | {
42 | this.throwAddingIncompatibleValueException(value);
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfDateTimeColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.compare.DateTimeComparisonResult;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.DateTimeValue;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
6 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
7 |
8 | import java.time.LocalDateTime;
9 | import java.time.format.DateTimeFormatter;
10 |
11 | public interface DfDateTimeColumn
12 | extends DfObjectColumn
13 | {
14 | DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_DATE_TIME;
15 |
16 | @Override
17 | default String getValueAsString(int rowIndex)
18 | {
19 | LocalDateTime value = this.getTypedObject(rowIndex);
20 | return value == null ? "" : this.FORMATTER.format(value);
21 | }
22 |
23 | @Override
24 | default ValueType getType()
25 | {
26 | return ValueType.DATE_TIME;
27 | }
28 |
29 | @Override
30 | default Value objectToValue(LocalDateTime anObject)
31 | {
32 | return new DateTimeValue(anObject);
33 | }
34 |
35 | @Override
36 | default void addRowToColumn(int rowIndex, DfColumn target)
37 | {
38 | ((DfDateTimeColumnStored) target).addMyType(this.getTypedObject(rowIndex));
39 | }
40 |
41 | @Override
42 | default DfCellComparator columnComparator(DfColumn otherColumn)
43 | {
44 | DfDateTimeColumn otherStringColumn = (DfDateTimeColumn) otherColumn;
45 |
46 | return (thisRowIndex, otherRowIndex) -> new DateTimeComparisonResult(
47 | this.getTypedObject(this.dataFrameRowIndex(thisRowIndex)),
48 | otherStringColumn.getTypedObject(otherStringColumn.dataFrameRowIndex(otherRowIndex)));
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfDateTimeColumnComputed.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.DateTimeValue;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
5 |
6 | import java.time.LocalDateTime;
7 |
8 | public class DfDateTimeColumnComputed
9 | extends DfObjectColumnComputed
10 | implements DfDateTimeColumn
11 | {
12 | public DfDateTimeColumnComputed(DataFrame newDataFrame, String newName, String newExpressionAsString)
13 | {
14 | super(newDataFrame, newName, newExpressionAsString);
15 | }
16 |
17 | @Override
18 | public LocalDateTime getTypedObject(int rowIndex)
19 | {
20 | Value result = this.getValue(rowIndex);
21 |
22 | return result.isVoid() ? null : ((DateTimeValue) result).dateTimeValue();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfDateTimeColumnStored.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.DateTimeValue;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
5 | import org.eclipse.collections.api.list.ListIterable;
6 |
7 | import java.time.LocalDateTime;
8 |
9 | public class DfDateTimeColumnStored
10 | extends DfObjectColumnStored
11 | implements DfDateTimeColumn
12 | {
13 | public DfDateTimeColumnStored(DataFrame owner, String newName)
14 | {
15 | super(owner, newName);
16 | }
17 |
18 | public DfDateTimeColumnStored(DataFrame owner, String newName, ListIterable newValues)
19 | {
20 | super(owner, newName, newValues);
21 | }
22 |
23 | @Override
24 | public void addObject(Object newObject)
25 | {
26 | this.addMyType((LocalDateTime) newObject);
27 | }
28 |
29 | @Override
30 | public void addValue(Value value)
31 | {
32 | if (value.isVoid())
33 | {
34 | this.addObject(null);
35 | }
36 | else if (value.isDateTime())
37 | {
38 | this.addMyType(((DateTimeValue) value).dateTimeValue());
39 | }
40 | else
41 | {
42 | this.throwAddingIncompatibleValueException(value);
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfDecimalColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.compare.DecimalComparisonResult;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.DecimalValue;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
6 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
7 |
8 | import java.math.BigDecimal;
9 |
10 | public interface DfDecimalColumn
11 | extends DfObjectColumn
12 | {
13 | @Override
14 | default String getValueAsString(int rowIndex)
15 | {
16 | BigDecimal value = this.getTypedObject(rowIndex);
17 | return value == null ? "" : value.toString();
18 | }
19 |
20 | @Override
21 | default ValueType getType()
22 | {
23 | return ValueType.DECIMAL;
24 | }
25 |
26 | @Override
27 | default Value objectToValue(BigDecimal anObject)
28 | {
29 | return new DecimalValue(anObject);
30 | }
31 |
32 | @Override
33 | default void addRowToColumn(int rowIndex, DfColumn target)
34 | {
35 | target.addObject(this.getTypedObject(rowIndex));
36 | }
37 |
38 | @Override
39 | default DfCellComparator columnComparator(DfColumn otherColumn)
40 | {
41 | DfDecimalColumn otherStringColumn = (DfDecimalColumn) otherColumn;
42 |
43 | return (thisRowIndex, otherRowIndex) -> new DecimalComparisonResult(
44 | this.getTypedObject(this.dataFrameRowIndex(thisRowIndex)),
45 | otherStringColumn.getTypedObject(otherStringColumn.dataFrameRowIndex(otherRowIndex)));
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfDecimalColumnComputed.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.DecimalValue;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
5 |
6 | import java.math.BigDecimal;
7 |
8 | public class DfDecimalColumnComputed
9 | extends DfObjectColumnComputed
10 | implements DfDecimalColumn
11 | {
12 | public DfDecimalColumnComputed(DataFrame newDataFrame, String newName, String newExpressionAsString)
13 | {
14 | super(newDataFrame, newName, newExpressionAsString);
15 | }
16 |
17 | @Override
18 | public BigDecimal getTypedObject(int rowIndex)
19 | {
20 | Value result = this.getValue(rowIndex);
21 |
22 | return result.isVoid() ? null : ((DecimalValue) result).decimalValue();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfDecimalColumnStored.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.DecimalValue;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
5 | import org.eclipse.collections.api.list.ListIterable;
6 |
7 | import java.math.BigDecimal;
8 |
9 | public class DfDecimalColumnStored
10 | extends DfObjectColumnStored
11 | implements DfDecimalColumn
12 | {
13 | public DfDecimalColumnStored(DataFrame owner, String newName)
14 | {
15 | super(owner, newName);
16 | }
17 |
18 | public DfDecimalColumnStored(DataFrame owner, String newName, ListIterable newValues)
19 | {
20 | super(owner, newName, newValues);
21 | }
22 |
23 | @Override
24 | public void addObject(Object newObject)
25 | {
26 | this.addMyType((BigDecimal) newObject);
27 | }
28 |
29 | @Override
30 | public void addValue(Value value)
31 | {
32 | if (value.isVoid())
33 | {
34 | this.addObject(null);
35 | }
36 | else if (value.isDecimal())
37 | {
38 | this.addMyType(((DecimalValue) value).decimalValue());
39 | }
40 | else
41 | {
42 | this.throwAddingIncompatibleValueException(value);
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfDoubleColumnComputed.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.Expression;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.DoubleValue;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
6 | import io.github.vmzakharov.ecdataframe.util.ExpressionParserHelper;
7 |
8 | public class DfDoubleColumnComputed
9 | extends DfDoubleColumn
10 | implements DfColumnComputed
11 | {
12 | private final String expressionAsString;
13 | private final Expression expression;
14 |
15 | public DfDoubleColumnComputed(DataFrame newDataFrame, String newName, String newExpressionAsString)
16 | {
17 | super(newDataFrame, newName);
18 | this.expressionAsString = newExpressionAsString;
19 |
20 | this.expression = ExpressionParserHelper.DEFAULT.toExpressionOrScript(this.expressionAsString);
21 | }
22 |
23 | @Override
24 | public Object getObject(int rowIndex)
25 | {
26 | Value result = this.getValue(rowIndex);
27 |
28 | return result.isVoid() ? null : ((DoubleValue) result).doubleValue();
29 | }
30 |
31 | @Override
32 | public double getDouble(int rowIndex)
33 | {
34 | Value result = this.getValue(rowIndex);
35 |
36 | if (result.isVoid())
37 | {
38 | throw new NullPointerException("Null value at " + this.getName() + "[" + rowIndex + "]");
39 | }
40 |
41 | return ((DoubleValue) result).doubleValue();
42 | }
43 |
44 | @Override
45 | protected void addAllItemsFrom(DfDoubleColumn doubleColumn)
46 | {
47 | this.throwUnmodifiableColumnException();
48 | }
49 |
50 | @Override
51 | public int getSize()
52 | {
53 | return this.getDataFrame().rowCount();
54 | }
55 |
56 | @Override
57 | public String getExpressionAsString()
58 | {
59 | return this.expressionAsString;
60 | }
61 |
62 | @Override
63 | public Expression getExpression()
64 | {
65 | return this.expression;
66 | }
67 |
68 | @Override
69 | public boolean isNull(int rowIndex)
70 | {
71 | return this.getObject(rowIndex) == null;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfFloatColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.compare.DoubleComparisonResult;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
5 | import org.eclipse.collections.api.FloatIterable;
6 | import org.eclipse.collections.api.list.primitive.ImmutableFloatList;
7 | import org.eclipse.collections.impl.factory.primitive.FloatLists;
8 | import org.eclipse.collections.impl.list.primitive.IntInterval;
9 |
10 | abstract public class DfFloatColumn
11 | extends DfColumnAbstract
12 | {
13 | public DfFloatColumn(DataFrame newDataFrame, String newName)
14 | {
15 | super(newDataFrame, newName);
16 | }
17 |
18 | abstract public float getFloat(int rowIndex);
19 |
20 | @Override
21 | public String getValueAsString(int rowIndex)
22 | {
23 | return Float.toString(this.getFloat(rowIndex));
24 | }
25 |
26 | public ImmutableFloatList toFloatList()
27 | {
28 | return this.asFloatIterable().toList().toImmutable();
29 | }
30 |
31 | public FloatIterable asFloatIterable()
32 | {
33 | int rowCount = this.getDataFrame().rowCount();
34 | if (rowCount == 0)
35 | {
36 | return FloatLists.immutable.empty();
37 | }
38 |
39 | return IntInterval.zeroTo(rowCount - 1)
40 | .asLazy()
41 | .collectFloat(this::getFloat);
42 | }
43 |
44 | @Override
45 | public ValueType getType()
46 | {
47 | return ValueType.FLOAT;
48 | }
49 |
50 | @Override
51 | public void addRowToColumn(int rowIndex, DfColumn target)
52 | {
53 | if (this.isNull(rowIndex))
54 | {
55 | target.addEmptyValue();
56 | }
57 | else
58 | {
59 | ((DfFloatColumnStored) target).addFloat(this.getFloat(rowIndex));
60 | }
61 | }
62 |
63 | @Override
64 | public DfColumn mergeWithInto(DfColumn other, DataFrame target)
65 | {
66 | DfFloatColumn mergedCol = (DfFloatColumn) this.validateAndCreateTargetColumn(other, target);
67 |
68 | mergedCol.addAllItemsFrom(this);
69 | mergedCol.addAllItemsFrom((DfFloatColumn) other);
70 |
71 | return mergedCol;
72 | }
73 |
74 | @Override
75 | public DfColumn copyTo(DataFrame target)
76 | {
77 | DfFloatColumn targetCol = (DfFloatColumn) this.copyColumnSchemaAndEnsureCapacity(target);
78 |
79 | targetCol.addAllItemsFrom(this);
80 | return targetCol;
81 | }
82 |
83 | protected abstract void addAllItemsFrom(DfFloatColumn items);
84 |
85 | @Override
86 | public DfCellComparator columnComparator(DfColumn otherColumn)
87 | {
88 | DfFloatColumn otherFloatColumn = (DfFloatColumn) otherColumn;
89 |
90 | return (thisRowIndex, otherRowIndex) -> {
91 | int thisMappedIndex = this.dataFrameRowIndex(thisRowIndex);
92 | int otherMappedIndex = otherFloatColumn.dataFrameRowIndex(otherRowIndex);
93 |
94 | return new DoubleComparisonResult(
95 | () -> this.getFloat(thisMappedIndex),
96 | () -> otherFloatColumn.getFloat(otherMappedIndex),
97 | this.isNull(thisMappedIndex),
98 | otherFloatColumn.isNull(otherMappedIndex)
99 | );
100 | };
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfFloatColumnComputed.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.Expression;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.FloatValue;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
6 | import io.github.vmzakharov.ecdataframe.util.ExpressionParserHelper;
7 |
8 | public class DfFloatColumnComputed
9 | extends DfFloatColumn
10 | implements DfColumnComputed
11 | {
12 | private final String expressionAsString;
13 | private final Expression expression;
14 |
15 | public DfFloatColumnComputed(DataFrame newDataFrame, String newName, String newExpressionAsString)
16 | {
17 | super(newDataFrame, newName);
18 | this.expressionAsString = newExpressionAsString;
19 |
20 | this.expression = ExpressionParserHelper.DEFAULT.toExpressionOrScript(this.expressionAsString);
21 | }
22 |
23 | @Override
24 | public Object getObject(int rowIndex)
25 | {
26 | Value result = this.getValue(rowIndex);
27 |
28 | return result.isVoid() ? null : ((FloatValue) result).floatValue();
29 | }
30 |
31 | @Override
32 | public float getFloat(int rowIndex)
33 | {
34 | Value result = this.getValue(rowIndex);
35 |
36 | if (result.isVoid())
37 | {
38 | throw new NullPointerException("Null value at " + this.getName() + "[" + rowIndex + "]");
39 | }
40 |
41 | return ((FloatValue) result).floatValue();
42 | }
43 |
44 | @Override
45 | protected void addAllItemsFrom(DfFloatColumn floatColumn)
46 | {
47 | this.throwUnmodifiableColumnException();
48 | }
49 |
50 | @Override
51 | public int getSize()
52 | {
53 | return this.getDataFrame().rowCount();
54 | }
55 |
56 | @Override
57 | public String getExpressionAsString()
58 | {
59 | return this.expressionAsString;
60 | }
61 |
62 | @Override
63 | public Expression getExpression()
64 | {
65 | return this.expression;
66 | }
67 |
68 | @Override
69 | public boolean isNull(int rowIndex)
70 | {
71 | return this.getObject(rowIndex) == null;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfIntColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.compare.LongComparisonResult;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
5 | import org.eclipse.collections.api.IntIterable;
6 | import org.eclipse.collections.api.list.primitive.ImmutableIntList;
7 | import org.eclipse.collections.impl.factory.primitive.IntLists;
8 | import org.eclipse.collections.impl.list.primitive.IntInterval;
9 |
10 | abstract public class DfIntColumn
11 | extends DfColumnAbstract
12 | {
13 | public DfIntColumn(DataFrame newDataFrame, String newName)
14 | {
15 | super(newDataFrame, newName);
16 | }
17 |
18 | abstract public int getInt(int rowIndex);
19 |
20 | @Override
21 | public String getValueAsString(int rowIndex)
22 | {
23 | return Integer.toString(this.getInt(rowIndex));
24 | }
25 |
26 | public ImmutableIntList toIntList()
27 | {
28 | return this.asIntIterable().toList().toImmutable();
29 | }
30 |
31 | public IntIterable asIntIterable()
32 | {
33 | int rowCount = this.getDataFrame().rowCount();
34 | if (rowCount == 0)
35 | {
36 | return IntLists.immutable.empty();
37 | }
38 |
39 | return IntInterval
40 | .zeroTo(rowCount - 1)
41 | .asLazy()
42 | .collectInt(this::getInt);
43 | }
44 |
45 | @Override
46 | public ValueType getType()
47 | {
48 | return ValueType.INT;
49 | }
50 |
51 | @Override
52 | public void addRowToColumn(int rowIndex, DfColumn target)
53 | {
54 | if (this.isNull(rowIndex))
55 | {
56 | target.addEmptyValue();
57 | }
58 | else
59 | {
60 | ((DfIntColumnStored) target).addInt(this.getInt(rowIndex), false);
61 | }
62 | }
63 |
64 | @Override
65 | public DfColumn mergeWithInto(DfColumn other, DataFrame target)
66 | {
67 | DfIntColumn mergedCol = (DfIntColumn) this.validateAndCreateTargetColumn(other, target);
68 |
69 | mergedCol.addAllItemsFrom(this);
70 | mergedCol.addAllItemsFrom((DfIntColumn) other);
71 |
72 | return mergedCol;
73 | }
74 |
75 | @Override
76 | public DfColumn copyTo(DataFrame target)
77 | {
78 | DfIntColumn targetCol = (DfIntColumn) this.copyColumnSchemaAndEnsureCapacity(target);
79 |
80 | targetCol.addAllItemsFrom(this);
81 | return targetCol;
82 | }
83 |
84 | protected abstract void addAllItemsFrom(DfIntColumn items);
85 |
86 | @Override
87 | public DfCellComparator columnComparator(DfColumn otherColumn)
88 | {
89 | DfIntColumn otherIntColumn = (DfIntColumn) otherColumn;
90 |
91 | return (thisRowIndex, otherRowIndex) -> {
92 | int thisMappedIndex = this.dataFrameRowIndex(thisRowIndex);
93 | int otherMappedIndex = otherIntColumn.dataFrameRowIndex(otherRowIndex);
94 |
95 | return new LongComparisonResult(
96 | () -> this.getInt(thisMappedIndex),
97 | () -> otherIntColumn.getInt(otherMappedIndex),
98 | this.isNull(thisMappedIndex),
99 | otherIntColumn.isNull(otherMappedIndex)
100 | );
101 | };
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfIntColumnComputed.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.Expression;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.IntValue;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
6 | import io.github.vmzakharov.ecdataframe.util.ExpressionParserHelper;
7 |
8 | public class DfIntColumnComputed
9 | extends DfIntColumn
10 | implements DfColumnComputed
11 | {
12 | private final String expressionAsString;
13 | private final Expression expression;
14 |
15 | public DfIntColumnComputed(DataFrame newDataFrame, String newName, String newExpressionAsString)
16 | {
17 | super(newDataFrame, newName);
18 | this.expressionAsString = newExpressionAsString;
19 | this.expression = ExpressionParserHelper.DEFAULT.toExpressionOrScript(this.expressionAsString);
20 | }
21 |
22 | @Override
23 | public int getInt(int rowIndex)
24 | {
25 | Value result = this.getValue(rowIndex);
26 |
27 | if (result.isVoid())
28 | {
29 | throw new NullPointerException("Null value at " + this.getName() + "[" + rowIndex + "]");
30 | }
31 |
32 | return ((IntValue) result).intValue();
33 | }
34 |
35 | @Override
36 | public Object getObject(int rowIndex)
37 | {
38 | Value result = this.getValue(rowIndex);
39 |
40 | return result.isVoid() ? null : ((IntValue) result).intValue();
41 | }
42 |
43 | @Override
44 | public boolean isNull(int rowIndex)
45 | {
46 | return this.getObject(rowIndex) == null;
47 | }
48 |
49 | @Override
50 | protected void addAllItemsFrom(DfIntColumn intColumn)
51 | {
52 | this.throwUnmodifiableColumnException();
53 | }
54 |
55 | @Override
56 | public int getSize()
57 | {
58 | return this.getDataFrame().rowCount();
59 | }
60 |
61 | @Override
62 | public String getExpressionAsString()
63 | {
64 | return this.expressionAsString;
65 | }
66 |
67 | @Override
68 | public Expression getExpression()
69 | {
70 | return this.expression;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfIterate.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import org.eclipse.collections.api.block.function.Function;
4 | import org.eclipse.collections.api.block.procedure.Procedure;
5 | import org.eclipse.collections.api.list.ListIterable;
6 | import org.eclipse.collections.impl.factory.Lists;
7 |
8 | import java.util.function.BiConsumer;
9 | import java.util.function.Supplier;
10 |
11 | /**
12 | * An interface defining common iteration patterns for data frames and data frame indices
13 | */
14 | public interface DfIterate
15 | {
16 | /**
17 | * Executes the procedure for each row in this dataframe iterable
18 | *
19 | * @param action the procedure to execute for each row
20 | */
21 | void forEach(Procedure action);
22 |
23 | /**
24 | * Creates a list from this dataframe iterable. The new collection is made up of the results of applying
25 | * the specified function to each row of the data frame iterable.
26 | *
27 | * @param action the function the result of which will be collected in the resulting collection
28 | * @param the type of the elements of the resulting collection
29 | * @return the list made up of the results of applying the specified action to each row of the data frame iterable
30 | */
31 | default ListIterable collect(Function action)
32 | {
33 | return this.collect(
34 | Lists.mutable::empty,
35 | (container, row) -> container.add(action.valueOf(row))
36 | );
37 | }
38 |
39 | /**
40 | * Performs a reduction operation on each row of the data frame iterable with the results accumulating in the
41 | * container provided by the supplier parameter.
42 | * @param supplier supplies the result container
43 | * @param accumulator a two argument function that takes the result container and the current row of the data frame
44 | * iterable
45 | * @return the result container
46 | * @param the type of the result reduction operation (result container)
47 | */
48 | default R collect(Supplier extends R> supplier, BiConsumer accumulator)
49 | {
50 | R result = supplier.get();
51 |
52 | this.forEach(row -> accumulator.accept(result, row));
53 |
54 | return result;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfLongColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.compare.LongComparisonResult;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
5 | import org.eclipse.collections.api.LongIterable;
6 | import org.eclipse.collections.api.list.primitive.ImmutableLongList;
7 | import org.eclipse.collections.impl.factory.primitive.LongLists;
8 | import org.eclipse.collections.impl.list.primitive.IntInterval;
9 |
10 | abstract public class DfLongColumn
11 | extends DfColumnAbstract
12 | {
13 | public DfLongColumn(DataFrame newDataFrame, String newName)
14 | {
15 | super(newDataFrame, newName);
16 | }
17 |
18 | abstract public long getLong(int rowIndex);
19 |
20 | @Override
21 | public String getValueAsString(int rowIndex)
22 | {
23 | return Long.toString(this.getLong(rowIndex));
24 | }
25 |
26 | public ImmutableLongList toLongList()
27 | {
28 | return this.asLongIterable().toList().toImmutable();
29 | }
30 |
31 | public LongIterable asLongIterable()
32 | {
33 | int rowCount = this.getDataFrame().rowCount();
34 | if (rowCount == 0)
35 | {
36 | return LongLists.immutable.empty();
37 | }
38 |
39 | return IntInterval.zeroTo(rowCount - 1)
40 | .asLazy()
41 | .collectLong(this::getLong);
42 | }
43 |
44 | @Override
45 | public ValueType getType()
46 | {
47 | return ValueType.LONG;
48 | }
49 |
50 | @Override
51 | public void addRowToColumn(int rowIndex, DfColumn target)
52 | {
53 | if (this.isNull(rowIndex))
54 | {
55 | target.addEmptyValue();
56 | }
57 | else
58 | {
59 | ((DfLongColumnStored) target).addLong(this.getLong(rowIndex), false);
60 | }
61 | }
62 |
63 | @Override
64 | public DfColumn mergeWithInto(DfColumn other, DataFrame target)
65 | {
66 | DfLongColumn mergedCol = (DfLongColumn) this.validateAndCreateTargetColumn(other, target);
67 |
68 | mergedCol.addAllItemsFrom(this);
69 | mergedCol.addAllItemsFrom((DfLongColumn) other);
70 |
71 | return mergedCol;
72 | }
73 |
74 | @Override
75 | public DfColumn copyTo(DataFrame target)
76 | {
77 | DfLongColumn targetCol = (DfLongColumn) this.copyColumnSchemaAndEnsureCapacity(target);
78 |
79 | targetCol.addAllItemsFrom(this);
80 | return targetCol;
81 | }
82 |
83 | protected abstract void addAllItemsFrom(DfLongColumn items);
84 |
85 | @Override
86 | public DfCellComparator columnComparator(DfColumn otherColumn)
87 | {
88 | DfLongColumn otherLongColumn = (DfLongColumn) otherColumn;
89 |
90 | return (thisRowIndex, otherRowIndex) -> {
91 | int thisMappedIndex = this.dataFrameRowIndex(thisRowIndex);
92 | int otherMappedIndex = otherLongColumn.dataFrameRowIndex(otherRowIndex);
93 |
94 | return new LongComparisonResult(
95 | () -> this.getLong(thisMappedIndex),
96 | () -> otherLongColumn.getLong(otherMappedIndex),
97 | this.isNull(thisMappedIndex),
98 | otherLongColumn.isNull(otherMappedIndex)
99 | );
100 | };
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfLongColumnComputed.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.Expression;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.LongValue;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
6 | import io.github.vmzakharov.ecdataframe.util.ExpressionParserHelper;
7 |
8 | public class DfLongColumnComputed
9 | extends DfLongColumn
10 | implements DfColumnComputed
11 | {
12 | private final String expressionAsString;
13 | private final Expression expression;
14 |
15 | public DfLongColumnComputed(DataFrame newDataFrame, String newName, String newExpressionAsString)
16 | {
17 | super(newDataFrame, newName);
18 | this.expressionAsString = newExpressionAsString;
19 | this.expression = ExpressionParserHelper.DEFAULT.toExpressionOrScript(this.expressionAsString);
20 | }
21 |
22 | @Override
23 | public long getLong(int rowIndex)
24 | {
25 | Value result = this.getValue(rowIndex);
26 |
27 | if (result.isVoid())
28 | {
29 | throw new NullPointerException("Null value at " + this.getName() + "[" + rowIndex + "]");
30 | }
31 |
32 | return ((LongValue) result).longValue();
33 | }
34 |
35 | @Override
36 | public Object getObject(int rowIndex)
37 | {
38 | Value result = this.getValue(rowIndex);
39 |
40 | return result.isVoid() ? null : ((LongValue) result).longValue();
41 | }
42 |
43 | @Override
44 | public boolean isNull(int rowIndex)
45 | {
46 | return this.getObject(rowIndex) == null;
47 | }
48 |
49 | @Override
50 | protected void addAllItemsFrom(DfLongColumn longColumn)
51 | {
52 | this.throwUnmodifiableColumnException();
53 | }
54 |
55 | @Override
56 | public int getSize()
57 | {
58 | return this.getDataFrame().rowCount();
59 | }
60 |
61 | @Override
62 | public String getExpressionAsString()
63 | {
64 | return this.expressionAsString;
65 | }
66 |
67 | @Override
68 | public Expression getExpression()
69 | {
70 | return this.expression;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfObjectColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import org.eclipse.collections.api.block.function.Function2;
5 | import org.eclipse.collections.api.list.ImmutableList;
6 |
7 | public interface DfObjectColumn
8 | extends DfColumn
9 | {
10 | ImmutableList toList();
11 |
12 | T getTypedObject(int rowIndex);
13 |
14 | Value objectToValue(T anObject);
15 |
16 | @Override
17 | default Object getObject(int rowIndex)
18 | {
19 | return this.getTypedObject(rowIndex);
20 | }
21 |
22 | default IV injectIntoBreakOnNulls(
23 | IV injectedValue,
24 | Function2 function
25 | )
26 | {
27 | IV result = injectedValue;
28 |
29 | for (int i = 0; i < this.getSize(); i++)
30 | {
31 | T current = this.getTypedObject(i);
32 | if (current == null)
33 | {
34 | return null;
35 | }
36 |
37 | result = function.apply(result, current);
38 |
39 | if (result == null)
40 | {
41 | return null;
42 | }
43 | }
44 |
45 | return result;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfObjectColumnAbstract.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import org.eclipse.collections.api.list.ListIterable;
4 |
5 | abstract public class DfObjectColumnAbstract
6 | extends DfColumnAbstract
7 | implements DfObjectColumn
8 | {
9 | public DfObjectColumnAbstract(DataFrame newDataFrame, String newName)
10 | {
11 | super(newDataFrame, newName);
12 | }
13 |
14 | @Override
15 | public boolean isNull(int rowIndex)
16 | {
17 | return this.getObject(rowIndex) == null;
18 | }
19 |
20 | abstract protected void addAllItems(ListIterable items);
21 |
22 | @Override
23 | public DfColumn mergeWithInto(DfColumn other, DataFrame target)
24 | {
25 | DfObjectColumnAbstract mergedCol = (DfObjectColumnAbstract) this.validateAndCreateTargetColumn(other, target);
26 |
27 | mergedCol.addAllItems(this.toList());
28 | mergedCol.addAllItems(((DfObjectColumnAbstract) other).toList());
29 | return mergedCol;
30 | }
31 |
32 | @Override
33 | public DfColumn copyTo(DataFrame target)
34 | {
35 | DfObjectColumnAbstract targetCol = (DfObjectColumnAbstract) this.copyColumnSchemaAndEnsureCapacity(target);
36 |
37 | targetCol.addAllItems(this.toList());
38 | return targetCol;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfObjectColumnComputed.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.Expression;
4 | import io.github.vmzakharov.ecdataframe.util.ExpressionParserHelper;
5 | import org.eclipse.collections.api.list.ImmutableList;
6 | import org.eclipse.collections.api.list.ListIterable;
7 | import org.eclipse.collections.impl.factory.Lists;
8 | import org.eclipse.collections.impl.list.primitive.IntInterval;
9 |
10 | abstract public class DfObjectColumnComputed
11 | extends DfObjectColumnAbstract
12 | implements DfColumnComputed
13 | {
14 | private final String expressionAsString;
15 | private final Expression expression;
16 |
17 | public DfObjectColumnComputed(DataFrame newDataFrame, String newName, String newExpressionAsString)
18 | {
19 | super(newDataFrame, newName);
20 | this.expressionAsString = newExpressionAsString;
21 | this.expression = ExpressionParserHelper.DEFAULT.toExpressionOrScript(this.expressionAsString);
22 | }
23 |
24 | @Override
25 | public ImmutableList toList()
26 | {
27 | int rowCount = this.getDataFrame().rowCount();
28 | if (rowCount == 0)
29 | {
30 | return Lists.immutable.empty();
31 | }
32 |
33 | return IntInterval
34 | .zeroTo(rowCount - 1)
35 | .collect(this::getTypedObject, Lists.mutable.withInitialCapacity(rowCount))
36 | .toImmutable();
37 | }
38 |
39 | @Override
40 | public int getSize()
41 | {
42 | return this.getDataFrame().rowCount();
43 | }
44 |
45 | @Override
46 | public String getExpressionAsString()
47 | {
48 | return this.expressionAsString;
49 | }
50 |
51 | @Override
52 | public Expression getExpression()
53 | {
54 | return this.expression;
55 | }
56 |
57 | @Override
58 | protected void addAllItems(ListIterable items)
59 | {
60 | this.throwUnmodifiableColumnException();
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfStringColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.compare.StringComparisonResult;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.StringValue;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
6 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
7 |
8 | public interface DfStringColumn
9 | extends DfObjectColumn
10 | {
11 | @Override
12 | default String getValueAsString(int rowIndex)
13 | {
14 | return this.getTypedObject(rowIndex);
15 | }
16 |
17 | @Override
18 | default String getValueAsStringLiteral(int rowIndex)
19 | {
20 | String value = this.getTypedObject(rowIndex);
21 | return value == null ? "" : '"' + this.getValueAsString(rowIndex) + '"';
22 | }
23 |
24 | @Override
25 | default ValueType getType()
26 | {
27 | return ValueType.STRING;
28 | }
29 |
30 | @Override
31 | default Value objectToValue(String anObject)
32 | {
33 | return new StringValue(anObject);
34 | }
35 |
36 | @Override
37 | default void addRowToColumn(int rowIndex, DfColumn target)
38 | {
39 | target.addObject(this.getTypedObject(rowIndex));
40 | }
41 |
42 | @Override
43 | default DfCellComparator columnComparator(DfColumn otherColumn)
44 | {
45 | DfStringColumn otherStringColumn = (DfStringColumn) otherColumn;
46 |
47 | return (thisRowIndex, otherRowIndex) -> new StringComparisonResult(
48 | this.getTypedObject(this.dataFrameRowIndex(thisRowIndex)),
49 | otherStringColumn.getTypedObject(otherStringColumn.dataFrameRowIndex(otherRowIndex)));
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfStringColumnComputed.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 |
5 | public class DfStringColumnComputed
6 | extends DfObjectColumnComputed
7 | implements DfStringColumn
8 | {
9 | public DfStringColumnComputed(DataFrame newDataFrame, String newName, String newExpressionAsString)
10 | {
11 | super(newDataFrame, newName, newExpressionAsString);
12 | }
13 |
14 | @Override
15 | public String getTypedObject(int rowIndex)
16 | {
17 | Value result = this.getValue(rowIndex);
18 |
19 | return result.isVoid() ? null : result.stringValue();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfStringColumnStored.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import org.eclipse.collections.api.list.ListIterable;
5 |
6 | public class DfStringColumnStored
7 | extends DfObjectColumnStored
8 | implements DfStringColumn
9 | {
10 | public DfStringColumnStored(DataFrame owner, String newName)
11 | {
12 | super(owner, newName);
13 | }
14 |
15 | public DfStringColumnStored(DataFrame owner, String newName, ListIterable newValues)
16 | {
17 | super(owner, newName, newValues);
18 | }
19 |
20 | @Override
21 | public void addValue(Value value)
22 | {
23 | if (value.isVoid())
24 | {
25 | this.addObject(null);
26 | }
27 | else if (value.isString())
28 | {
29 | this.addMyType(value.stringValue());
30 | }
31 | else
32 | {
33 | this.throwAddingIncompatibleValueException(value);
34 | }
35 | }
36 |
37 | @Override
38 | public void addObject(Object newObject)
39 | {
40 | this.addMyType((String) newObject);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/DfTuple.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import org.eclipse.collections.api.list.ListIterable;
4 | import org.eclipse.collections.impl.utility.ArrayIterate;
5 |
6 | import java.util.Arrays;
7 |
8 | public class DfTuple
9 | implements Comparable
10 | {
11 | private final Object[] items;
12 | private final int order;
13 |
14 | public DfTuple(int newOrder, Object... newItems)
15 | {
16 | this.order = newOrder;
17 | this.items = newItems;
18 | }
19 |
20 | public static int compareMindingNulls(Object thisItem, Object thatItem)
21 | {
22 | if (thisItem == null)
23 | {
24 | return thatItem == null ? 0 : -1;
25 | }
26 | else if (thatItem == null)
27 | {
28 | return 1;
29 | }
30 |
31 | return ((Comparable) thisItem).compareTo(thatItem);
32 | }
33 |
34 | @Override
35 | public boolean equals(Object o)
36 | {
37 | if (o instanceof DfTuple dfTuple)
38 | {
39 | return Arrays.equals(this.items, dfTuple.items);
40 | }
41 |
42 | return false;
43 | }
44 |
45 | @Override
46 | public int hashCode()
47 | {
48 | return Arrays.hashCode(this.items);
49 | }
50 |
51 | @Override
52 | public String toString()
53 | {
54 | return this.order + ":" + ArrayIterate.makeString(this.items);
55 | }
56 |
57 | public int order()
58 | {
59 | return this.order;
60 | }
61 |
62 | @Override
63 | public int compareTo(DfTuple other)
64 | {
65 | return this.compareTo(other, null);
66 | }
67 |
68 | public int compareTo(DfTuple other, ListIterable sortOrders)
69 | {
70 | Object[] theseItems = this.items;
71 |
72 | for (int i = 0; i < theseItems.length; i++)
73 | {
74 | int result = compareMindingNulls(theseItems[i], other.items[i]);
75 |
76 | if (result != 0)
77 | {
78 | return sortOrders == null ? result : sortOrders.get(i).order(result);
79 | }
80 | }
81 |
82 | return 0;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/aggregation/Count.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe.aggregation;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.AggregateFunction;
4 | import io.github.vmzakharov.ecdataframe.dataframe.DfColumn;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
6 | import org.eclipse.collections.api.list.ListIterable;
7 | import org.eclipse.collections.impl.factory.Lists;
8 |
9 | import static io.github.vmzakharov.ecdataframe.dsl.value.ValueType.DATE;
10 | import static io.github.vmzakharov.ecdataframe.dsl.value.ValueType.DATE_TIME;
11 | import static io.github.vmzakharov.ecdataframe.dsl.value.ValueType.DECIMAL;
12 | import static io.github.vmzakharov.ecdataframe.dsl.value.ValueType.DOUBLE;
13 | import static io.github.vmzakharov.ecdataframe.dsl.value.ValueType.FLOAT;
14 | import static io.github.vmzakharov.ecdataframe.dsl.value.ValueType.INT;
15 | import static io.github.vmzakharov.ecdataframe.dsl.value.ValueType.LONG;
16 | import static io.github.vmzakharov.ecdataframe.dsl.value.ValueType.STRING;
17 |
18 | public class Count
19 | extends AggregateFunction
20 | {
21 | private static final ListIterable SUPPORTED_TYPES = Lists.immutable.of(INT, LONG, DOUBLE, FLOAT, STRING, DATE, DATE_TIME, DECIMAL);
22 |
23 | public Count(String newColumnName)
24 | {
25 | super(newColumnName);
26 | }
27 |
28 | public Count(String newColumnName, String newTargetColumnName)
29 | {
30 | super(newColumnName, newTargetColumnName);
31 | }
32 |
33 | @Override
34 | public ValueType targetColumnType(ValueType sourceColumnType)
35 | {
36 | return ValueType.LONG;
37 | }
38 |
39 | @Override
40 | public ListIterable supportedSourceTypes()
41 | {
42 | return SUPPORTED_TYPES;
43 | }
44 |
45 | @Override
46 | public boolean nullsArePoisonous()
47 | {
48 | return false;
49 | }
50 |
51 | @Override
52 | public String getDescription()
53 | {
54 | return "Count the number of rows in a set or a group within a set";
55 | }
56 |
57 | @Override
58 | public Object applyToColumn(DfColumn column)
59 | {
60 | return column.getSize();
61 | }
62 |
63 | @Override
64 | public long getLongValue(DfColumn sourceColumn, int sourceRowIndex)
65 | {
66 | return 0;
67 | }
68 |
69 | @Override
70 | protected long longAccumulator(long currentAggregate, long newValue)
71 | {
72 | return currentAggregate + 1;
73 | }
74 |
75 | @Override
76 | public long longInitialValue()
77 | {
78 | return 0;
79 | }
80 |
81 | @Override
82 | public Object valueForEmptyColumn(DfColumn column)
83 | {
84 | return 0;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/compare/BooleanComparisonResult.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe.compare;
2 |
3 | import java.util.function.BooleanSupplier;
4 |
5 | public class BooleanComparisonResult
6 | extends ComparisonResult
7 | {
8 | private int delta;
9 |
10 | public BooleanComparisonResult(BooleanSupplier thisValueSupplier, BooleanSupplier otherValueSupplier, boolean thisIsNull, boolean otherIsNull)
11 | {
12 | this.dealWithNullsIfAny(thisIsNull, otherIsNull);
13 |
14 | if (this.noNulls())
15 | {
16 | boolean thisValue = thisValueSupplier.getAsBoolean();
17 | boolean otherValue = otherValueSupplier.getAsBoolean();
18 |
19 | this.delta(Boolean.compare(thisValue, otherValue));
20 | }
21 | }
22 |
23 | @Override
24 | public long delta()
25 | {
26 | return this.delta;
27 | }
28 |
29 | @Override
30 | protected void delta(int newDelta)
31 | {
32 | this.delta = newDelta;
33 | }
34 |
35 | @Override
36 | public int compared()
37 | {
38 | return Integer.compare(this.delta, 0);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/compare/DateComparisonResult.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe.compare;
2 |
3 | import java.time.LocalDate;
4 |
5 | public class DateComparisonResult
6 | extends ObjectComparisonResult
7 | {
8 | public DateComparisonResult(LocalDate thisObject, LocalDate thatObject)
9 | {
10 | super(thisObject, thatObject);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/compare/DateTimeComparisonResult.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe.compare;
2 |
3 | import java.time.LocalDateTime;
4 |
5 | public class DateTimeComparisonResult
6 | extends ObjectComparisonResult
7 | {
8 | public DateTimeComparisonResult(LocalDateTime thisObject, LocalDateTime thatObject)
9 | {
10 | super(thisObject, thatObject);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/compare/DecimalComparisonResult.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe.compare;
2 |
3 | import java.math.BigDecimal;
4 |
5 | public class DecimalComparisonResult
6 | extends ComparisonResult
7 | {
8 | private BigDecimal decDelta;
9 |
10 | public DecimalComparisonResult(BigDecimal thisObject, BigDecimal thatObject)
11 | {
12 | this.dealWithNullsIfAny(thisObject == null, thatObject == null);
13 |
14 | if (this.noNulls())
15 | {
16 | this.decDelta = thisObject.subtract(thatObject);
17 | }
18 | }
19 |
20 | @Override
21 | public double dDelta()
22 | {
23 | return this.decDelta.doubleValue();
24 | }
25 |
26 | public BigDecimal decDelta()
27 | {
28 | return this.decDelta;
29 | }
30 |
31 | @Override
32 | public int compared()
33 | {
34 | return this.decDelta.signum();
35 | }
36 |
37 | @Override
38 | public long delta()
39 | {
40 | return this.decDelta.longValue();
41 | }
42 |
43 | @Override
44 | protected void delta(int newDelta)
45 | {
46 | this.decDelta = BigDecimal.valueOf(newDelta);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/compare/DoubleComparisonResult.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe.compare;
2 |
3 | import java.util.function.DoubleSupplier;
4 |
5 | public class DoubleComparisonResult
6 | extends ComparisonResult
7 | {
8 | private double delta;
9 |
10 | public DoubleComparisonResult(DoubleSupplier thisValueSupplier, DoubleSupplier otherValueSupplier, boolean thisIsNull, boolean otherIsNull)
11 | {
12 | this.dealWithNullsIfAny(thisIsNull, otherIsNull);
13 |
14 | if (this.noNulls())
15 | {
16 | double thisValue = thisValueSupplier.getAsDouble();
17 | double otherValue = otherValueSupplier.getAsDouble();
18 | this.delta = thisValue - otherValue;
19 | }
20 | }
21 |
22 | @Override
23 | public long delta()
24 | {
25 | return Math.round(this.delta);
26 | }
27 |
28 | @Override
29 | public double dDelta()
30 | {
31 | return this.delta;
32 | }
33 |
34 | @Override
35 | protected void delta(int newDelta)
36 | {
37 | this.delta = newDelta;
38 | }
39 |
40 | @Override
41 | public int compared()
42 | {
43 | return Double.compare(this.delta, 0.0);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/compare/LongComparisonResult.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe.compare;
2 |
3 | import java.util.function.LongSupplier;
4 |
5 | public class LongComparisonResult
6 | extends ComparisonResult
7 | {
8 | private long delta;
9 |
10 | public LongComparisonResult(LongSupplier thisValueSupplier, LongSupplier otherValueSupplier, boolean thisIsNull, boolean otherIsNull)
11 | {
12 | this.dealWithNullsIfAny(thisIsNull, otherIsNull);
13 |
14 | if (this.noNulls())
15 | {
16 | long thisValue = thisValueSupplier.getAsLong();
17 | long otherValue = otherValueSupplier.getAsLong();
18 | this.delta = thisValue - otherValue;
19 |
20 | // check for overflows
21 | if ((thisValue > otherValue) && (this.delta < 0))
22 | {
23 | this.delta = Long.MAX_VALUE;
24 | }
25 | else if ((thisValue < otherValue) && (this.delta > 0))
26 | {
27 | this.delta = Long.MIN_VALUE;
28 | }
29 | }
30 | }
31 |
32 | @Override
33 | public long delta()
34 | {
35 | return this.delta;
36 | }
37 |
38 | @Override
39 | protected void delta(int newDelta)
40 | {
41 | this.delta = newDelta;
42 | }
43 |
44 | @Override
45 | public int compared()
46 | {
47 | return this.delta == 0 ? 0 : (this.delta > 0 ? 1 : -1);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/compare/ObjectComparisonResult.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe.compare;
2 |
3 | abstract public class ObjectComparisonResult>
4 | extends ComparisonResult
5 | {
6 | private int delta;
7 |
8 | public ObjectComparisonResult(T thisObject, T thatObject)
9 | {
10 | this.dealWithNullsIfAny(thisObject == null, thatObject == null);
11 |
12 | if (this.noNulls())
13 | {
14 | this.delta(thisObject.compareTo(thatObject));
15 | }
16 | }
17 |
18 | @Override
19 | public long delta()
20 | {
21 | return this.delta;
22 | }
23 |
24 | @Override
25 | protected void delta(int newDelta)
26 | {
27 | this.delta = newDelta;
28 | }
29 |
30 | @Override
31 | public int compared()
32 | {
33 | return this.delta;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataframe/compare/StringComparisonResult.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe.compare;
2 |
3 | public class StringComparisonResult
4 | extends ObjectComparisonResult
5 | {
6 | public StringComparisonResult(String thisObject, String thatObject)
7 | {
8 | super(thisObject, thatObject);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/BooleanFormatter.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import org.eclipse.collections.api.block.function.primitive.BooleanFunction;
4 | import org.eclipse.collections.impl.utility.StringIterate;
5 |
6 | import static io.github.vmzakharov.ecdataframe.util.ExceptionFactory.exceptionByKey;
7 |
8 | public class BooleanFormatter
9 | {
10 | private final BooleanFunction booleanParser;
11 | private final String trueString;
12 | private final String falseString;
13 |
14 | public BooleanFormatter(String pattern)
15 | {
16 | if (StringIterate.isEmpty(pattern))
17 | {
18 | this.trueString = "true";
19 | this.falseString = "false";
20 | }
21 | else if (pattern.contains(","))
22 | {
23 | String[] elements = pattern.split(",");
24 | this.trueString = elements[0];
25 | this.falseString = elements[1];
26 | }
27 | else
28 | {
29 | throw exceptionByKey("CSV_INVALID_FORMAT_STR")
30 | .with("format", pattern)
31 | .with("type", "boolean")
32 | .get();
33 | }
34 |
35 | this.booleanParser = s -> {
36 | if (this.trueString.equals(s)) return true;
37 | if (this.falseString.equals(s)) return false;
38 |
39 | throw exceptionByKey("CSV_PARSE_ERR")
40 | .with("type", "boolean")
41 | .with("inputString", s)
42 | .get();
43 | };
44 | }
45 |
46 | public boolean parseAsBoolean(String aString)
47 | {
48 | if (aString == null || aString.isEmpty())
49 | {
50 | return false;
51 | }
52 |
53 | return this.booleanParser.booleanValueOf(aString);
54 | }
55 |
56 | public String format(boolean booleanValue)
57 | {
58 | return booleanValue ? this.trueString : this.falseString;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/BooleanSchemaColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.DfBooleanColumn;
4 | import io.github.vmzakharov.ecdataframe.dataframe.DfBooleanColumnStored;
5 | import io.github.vmzakharov.ecdataframe.dataframe.DfColumn;
6 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
7 |
8 | public class BooleanSchemaColumn
9 | extends CsvSchemaColumn
10 | {
11 | final transient private BooleanFormatter booleanFormatter;
12 |
13 | public BooleanSchemaColumn(CsvSchema newCsvSchema, String newName, String newPattern)
14 | {
15 | super(newCsvSchema, newName, ValueType.BOOLEAN, newPattern);
16 |
17 | this.booleanFormatter = new BooleanFormatter(this.getPattern());
18 | }
19 |
20 | @Override
21 | public String formatColumnValueAsString(DfColumn column, int rowIndex)
22 | {
23 | boolean booleanValue = ((DfBooleanColumn) column).getBoolean(rowIndex);
24 | return this.booleanFormatter.format(booleanValue);
25 | }
26 |
27 | @Override
28 | public void parseAndAddToColumn(String aString, DfColumn dfColumn)
29 | {
30 | if (aString == null)
31 | {
32 | dfColumn.addEmptyValue();
33 | return;
34 | }
35 |
36 | ((DfBooleanColumnStored) dfColumn).addBoolean(this.booleanFormatter.parseAsBoolean(aString), false);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/CsvSchemaColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.DfColumn;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
5 |
6 | public abstract class CsvSchemaColumn
7 | {
8 | private final String name;
9 | private final ValueType type;
10 | private String pattern;
11 |
12 | transient private final CsvSchema csvSchema;
13 |
14 | public CsvSchemaColumn(CsvSchema newCsvSchema, String newName, ValueType newType, String newPattern)
15 | {
16 | this.csvSchema = newCsvSchema;
17 | this.name = newName;
18 | this.type = newType;
19 | this.pattern = newPattern;
20 | }
21 |
22 | protected CsvSchema csvSchema()
23 | {
24 | return this.csvSchema;
25 | }
26 |
27 | public String getName()
28 | {
29 | return this.name;
30 | }
31 |
32 | public ValueType getType()
33 | {
34 | return this.type;
35 | }
36 |
37 | public String getPattern()
38 | {
39 | return this.pattern;
40 | }
41 |
42 | protected void setPattern(String newPattern)
43 | {
44 | this.pattern = newPattern;
45 | }
46 |
47 | abstract public void parseAndAddToColumn(String aString, DfColumn dfColumn);
48 |
49 | abstract public String formatColumnValueAsString(DfColumn column, int rowIndex);
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/DataSet.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | public interface DataSet
4 | {
5 | void openFileForReading();
6 |
7 | String getName();
8 |
9 | /**
10 | * Returns the next element in the data set.
11 | * @return the next element in the data set
12 | */
13 | Object next();
14 |
15 | boolean hasNext();
16 |
17 | void close();
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/DataSetAbstract.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | abstract public class DataSetAbstract
4 | implements DataSet
5 | {
6 | private final String name;
7 |
8 | public DataSetAbstract(String newName)
9 | {
10 | this.name = newName;
11 | }
12 |
13 | @Override
14 | public String getName()
15 | {
16 | return this.name;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/DateSchemaColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.DfColumn;
4 | import io.github.vmzakharov.ecdataframe.dataframe.DfDateColumn;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
6 |
7 | import java.time.LocalDate;
8 | import java.time.format.DateTimeFormatter;
9 | import java.time.format.ResolverStyle;
10 |
11 | public class DateSchemaColumn
12 | extends CsvSchemaColumn
13 | {
14 | final transient private DateTimeFormatter dateTimeFormatter;
15 |
16 | public DateSchemaColumn(CsvSchema newCsvSchema, String newName, String newPattern)
17 | {
18 | super(newCsvSchema, newName, ValueType.DATE, newPattern);
19 |
20 | if (newPattern == null)
21 | {
22 | this.setPattern("uuuu-M-d");
23 | }
24 |
25 | this.dateTimeFormatter = DateTimeFormatter.ofPattern(this.getPattern()).withResolverStyle(ResolverStyle.STRICT);
26 | }
27 |
28 | @Override
29 | public String formatColumnValueAsString(DfColumn column, int rowIndex)
30 | {
31 | LocalDate dateValue = ((DfDateColumn) column).getTypedObject(rowIndex);
32 | return this.dateTimeFormatter.format(dateValue);
33 | }
34 |
35 | @Override
36 | public void parseAndAddToColumn(String aString, DfColumn dfColumn)
37 | {
38 | dfColumn.addObject(this.parseAsLocalDate(aString));
39 | }
40 |
41 | private LocalDate parseAsLocalDate(String aString)
42 | {
43 | if (aString == null)
44 | {
45 | return null;
46 | }
47 |
48 | String trimmed = aString.trim();
49 |
50 | return trimmed.isEmpty() ? null : LocalDate.parse(trimmed, this.dateTimeFormatter);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/DateTimeSchemaColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.DfColumn;
4 | import io.github.vmzakharov.ecdataframe.dataframe.DfDateTimeColumn;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
6 |
7 | import java.time.LocalDateTime;
8 | import java.time.format.DateTimeFormatter;
9 | import java.time.format.ResolverStyle;
10 |
11 | public class DateTimeSchemaColumn
12 | extends CsvSchemaColumn
13 | {
14 | final transient private DateTimeFormatter dateTimeFormatter;
15 |
16 | public DateTimeSchemaColumn(CsvSchema newCsvSchema, String newName, String newPattern)
17 | {
18 | super(newCsvSchema, newName, ValueType.DATE_TIME, newPattern);
19 |
20 | if (newPattern == null)
21 | {
22 | this.setPattern("uuuu-M-d'T'H:m:s");
23 | }
24 |
25 | this.dateTimeFormatter = DateTimeFormatter.ofPattern(this.getPattern()).withResolverStyle(ResolverStyle.STRICT);
26 | }
27 |
28 | @Override
29 | public String formatColumnValueAsString(DfColumn column, int rowIndex)
30 | {
31 | LocalDateTime dateTimeValue = ((DfDateTimeColumn) column).getTypedObject(rowIndex);
32 | return this.dateTimeFormatter.format(dateTimeValue);
33 | }
34 |
35 | @Override
36 | public void parseAndAddToColumn(String aString, DfColumn dfColumn)
37 | {
38 | dfColumn.addObject(this.parseAsLocalDateTime(aString));
39 | }
40 |
41 | private LocalDateTime parseAsLocalDateTime(String aString)
42 | {
43 | if (aString == null)
44 | {
45 | return null;
46 | }
47 |
48 | String trimmed = aString.trim();
49 |
50 | return trimmed.isEmpty() ? null : LocalDateTime.parse(trimmed, this.dateTimeFormatter);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/DecimalFormatter.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import org.eclipse.collections.api.block.function.Function;
4 | import org.eclipse.collections.impl.utility.StringIterate;
5 |
6 | import java.math.BigDecimal;
7 | import java.text.DecimalFormat;
8 | import java.text.ParseException;
9 | import java.util.regex.Pattern;
10 |
11 | import static io.github.vmzakharov.ecdataframe.util.ExceptionFactory.exceptionByKey;
12 |
13 | public class DecimalFormatter
14 | {
15 | private DecimalFormat decimalFormat;
16 | private final Function decimalParser;
17 | private Pattern nonNumericPattern;
18 |
19 | public DecimalFormatter(String pattern)
20 | {
21 | if (StringIterate.isEmpty(pattern))
22 | {
23 | this.decimalParser = BigDecimal::new;
24 | }
25 | else if (pattern.length() == 1)
26 | {
27 | this.nonNumericPattern = Pattern.compile("[^0-9" + pattern + "]");
28 | this.decimalParser = s -> new BigDecimal(this.stripNonNumericCharacters(s).replace(pattern, "."));
29 | }
30 | else
31 | {
32 | this.decimalFormat = new DecimalFormat(pattern);
33 | this.decimalFormat.setParseBigDecimal(true);
34 |
35 | this.decimalParser = s -> {
36 | try
37 | {
38 | return (BigDecimal) this.decimalFormat.parse(s.trim());
39 | }
40 | catch (ParseException e)
41 | {
42 | throw exceptionByKey("CSV_PARSE_ERR")
43 | .with("type", "a floating point number")
44 | .with("inputString", s).get(e);
45 | }
46 | };
47 | }
48 | }
49 |
50 | public BigDecimal parseAsDecimal(String aString)
51 | {
52 | if (aString == null || aString.isEmpty())
53 | {
54 | return null;
55 | }
56 |
57 | return this.decimalParser.apply(aString);
58 | }
59 |
60 | private String stripNonNumericCharacters(String s)
61 | {
62 | return this.nonNumericPattern.matcher(s).replaceAll("");
63 | }
64 |
65 | public String format(BigDecimal decimalValue)
66 | {
67 | return this.decimalFormat == null ? String.valueOf(decimalValue) : this.decimalFormat.format(decimalValue);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/DecimalSchemaColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.DfColumn;
4 | import io.github.vmzakharov.ecdataframe.dataframe.DfDecimalColumn;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
6 |
7 | import java.math.BigDecimal;
8 |
9 | public class DecimalSchemaColumn
10 | extends CsvSchemaColumn
11 | {
12 | final transient private DecimalFormatter decimalFormatter;
13 |
14 | public DecimalSchemaColumn(CsvSchema newCsvSchema, String newName, String newPattern)
15 | {
16 | super(newCsvSchema, newName, ValueType.DECIMAL, newPattern);
17 | this.decimalFormatter = new DecimalFormatter(newPattern);
18 | }
19 |
20 | @Override
21 | public String formatColumnValueAsString(DfColumn column, int rowIndex)
22 | {
23 | BigDecimal decimalValue = ((DfDecimalColumn) column).getTypedObject(rowIndex);
24 | return this.decimalFormatter.format(decimalValue);
25 | }
26 |
27 | @Override
28 | public void parseAndAddToColumn(String aString, DfColumn dfColumn)
29 | {
30 | dfColumn.addObject(this.decimalFormatter.parseAsDecimal(aString));
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/DoubleFormatter.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import org.eclipse.collections.api.block.function.primitive.DoubleFunction;
4 | import org.eclipse.collections.impl.utility.StringIterate;
5 |
6 | import java.text.DecimalFormat;
7 | import java.text.ParseException;
8 | import java.util.regex.Pattern;
9 |
10 | import static io.github.vmzakharov.ecdataframe.util.ExceptionFactory.exceptionByKey;
11 |
12 | public class DoubleFormatter
13 | {
14 | private DecimalFormat decimalFormat;
15 | private DoubleFunction doubleParser;
16 | private Pattern nonNumericPattern;
17 |
18 | public DoubleFormatter(String pattern)
19 | {
20 | if (StringIterate.isEmpty(pattern))
21 | {
22 | this.doubleParser = Double::parseDouble;
23 | }
24 | else if (pattern.length() == 1)
25 | {
26 | this.nonNumericPattern = Pattern.compile("[^0-9" + pattern + "]");
27 | this.doubleParser = s -> Double.parseDouble(this.stripNonNumericCharacters(s).replace(pattern, "."));
28 | }
29 | else
30 | {
31 | this.decimalFormat = new DecimalFormat(pattern);
32 | this.doubleParser = s -> {
33 | try
34 | {
35 | return this.decimalFormat.parse(s.trim()).doubleValue();
36 | }
37 | catch (ParseException e)
38 | {
39 | throw exceptionByKey("CSV_PARSE_ERR")
40 | .with("type", "a floating point number")
41 | .with("inputString", s).get(e);
42 | }
43 | };
44 | }
45 | }
46 |
47 | public double parseAsDouble(String aString)
48 | {
49 | if (aString == null || aString.isEmpty())
50 | {
51 | return 0.0;
52 | }
53 |
54 | return this.doubleParser.applyAsDouble(aString);
55 | }
56 |
57 | private String stripNonNumericCharacters(String s)
58 | {
59 | return this.nonNumericPattern.matcher(s).replaceAll("");
60 | }
61 |
62 | public String format(double doubleValue)
63 | {
64 | return this.decimalFormat == null ? Double.toString(doubleValue) : this.decimalFormat.format(doubleValue);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/DoubleSchemaColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.DfColumn;
4 | import io.github.vmzakharov.ecdataframe.dataframe.DfDoubleColumn;
5 | import io.github.vmzakharov.ecdataframe.dataframe.DfDoubleColumnStored;
6 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
7 |
8 | public class DoubleSchemaColumn
9 | extends CsvSchemaColumn
10 | {
11 | final transient private DoubleFormatter doubleFormatter;
12 |
13 | public DoubleSchemaColumn(CsvSchema newCsvSchema, String newName, String newPattern)
14 | {
15 | super(newCsvSchema, newName, ValueType.DOUBLE, newPattern);
16 |
17 | this.doubleFormatter = new DoubleFormatter(this.getPattern());
18 | }
19 |
20 | @Override
21 | public String formatColumnValueAsString(DfColumn column, int rowIndex)
22 | {
23 | double doubleValue = ((DfDoubleColumn) column).getDouble(rowIndex);
24 | return this.doubleFormatter.format(doubleValue);
25 | }
26 |
27 | @Override
28 | public void parseAndAddToColumn(String aString, DfColumn dfColumn)
29 | {
30 | if (aString == null)
31 | {
32 | dfColumn.addEmptyValue();
33 | return;
34 | }
35 |
36 | ((DfDoubleColumnStored) dfColumn).addDouble(this.doubleFormatter.parseAsDouble(aString));
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/FloatFormatter.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import org.eclipse.collections.api.block.function.primitive.FloatFunction;
4 | import org.eclipse.collections.impl.utility.StringIterate;
5 |
6 | import java.text.DecimalFormat;
7 | import java.text.ParseException;
8 | import java.util.regex.Pattern;
9 |
10 | import static io.github.vmzakharov.ecdataframe.util.ExceptionFactory.exceptionByKey;
11 |
12 | public class FloatFormatter
13 | {
14 | private DecimalFormat decimalFormat;
15 | private final FloatFunction floatParser;
16 | private Pattern nonNumericPattern;
17 |
18 | public FloatFormatter(String pattern)
19 | {
20 | if (StringIterate.isEmpty(pattern))
21 | {
22 | this.floatParser = Float::parseFloat;
23 | }
24 | else if (pattern.length() == 1)
25 | {
26 | this.nonNumericPattern = Pattern.compile("[^0-9" + pattern + "]");
27 | this.floatParser = s -> Float.parseFloat(this.stripNonNumericCharacters(s).replace(pattern, "."));
28 | }
29 | else
30 | {
31 | this.decimalFormat = new DecimalFormat(pattern);
32 | this.floatParser = s -> {
33 | try
34 | {
35 | return this.decimalFormat.parse(s.trim()).floatValue();
36 | }
37 | catch (ParseException e)
38 | {
39 | throw exceptionByKey("CSV_PARSE_ERR")
40 | .with("type", "a floating point number")
41 | .with("inputString", s).get(e);
42 | }
43 | };
44 | }
45 | }
46 |
47 | public float parseAsFloat(String aString)
48 | {
49 | if (aString == null || aString.isEmpty())
50 | {
51 | return 0.0f;
52 | }
53 |
54 | return this.floatParser.floatValueOf(aString);
55 | }
56 |
57 | private String stripNonNumericCharacters(String s)
58 | {
59 | return this.nonNumericPattern.matcher(s).replaceAll("");
60 | }
61 |
62 | public String format(float floatValue)
63 | {
64 | return this.decimalFormat == null ? Float.toString(floatValue) : this.decimalFormat.format(floatValue);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/FloatSchemaColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.DfColumn;
4 | import io.github.vmzakharov.ecdataframe.dataframe.DfFloatColumn;
5 | import io.github.vmzakharov.ecdataframe.dataframe.DfFloatColumnStored;
6 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
7 |
8 | public class FloatSchemaColumn
9 | extends CsvSchemaColumn
10 | {
11 | final transient private FloatFormatter floatFormatter;
12 |
13 | public FloatSchemaColumn(CsvSchema newCsvSchema, String newName, String newPattern)
14 | {
15 | super(newCsvSchema, newName, ValueType.FLOAT, newPattern);
16 |
17 | this.floatFormatter = new FloatFormatter(this.getPattern());
18 | }
19 |
20 | @Override
21 | public String formatColumnValueAsString(DfColumn column, int rowIndex)
22 | {
23 | float floatValue = ((DfFloatColumn) column).getFloat(rowIndex);
24 | return this.floatFormatter.format(floatValue);
25 | }
26 |
27 | @Override
28 | public void parseAndAddToColumn(String aString, DfColumn dfColumn)
29 | {
30 | if (aString == null)
31 | {
32 | dfColumn.addEmptyValue();
33 | return;
34 | }
35 |
36 | ((DfFloatColumnStored) dfColumn).addFloat(this.floatFormatter.parseAsFloat(aString));
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/HierarchicalDataSet.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
4 |
5 | abstract public class HierarchicalDataSet
6 | extends DataSetAbstract
7 | {
8 | public HierarchicalDataSet(String newName)
9 | {
10 | super(newName);
11 | }
12 |
13 | abstract public Object getValue(String propertyChainString);
14 |
15 | abstract public ValueType getFieldType(String fieldName);
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/IntFormatter.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import java.text.DecimalFormat;
4 | import java.text.ParseException;
5 | import java.util.regex.Pattern;
6 |
7 | import org.eclipse.collections.api.block.function.primitive.IntFunction;
8 | import org.eclipse.collections.impl.utility.StringIterate;
9 |
10 | import static io.github.vmzakharov.ecdataframe.util.ExceptionFactory.exceptionByKey;
11 |
12 | public class IntFormatter
13 | {
14 | private DecimalFormat decimalFormat;
15 | private IntFunction intParser;
16 | private Pattern nonNumericPattern;
17 |
18 | public IntFormatter(String pattern)
19 | {
20 | if (StringIterate.isEmpty(pattern))
21 | {
22 | this.intParser = Integer::parseInt;
23 | }
24 | else if (pattern.length() == 1)
25 | {
26 | this.nonNumericPattern = Pattern.compile("[^0-9" + pattern + "]");
27 | this.intParser = s -> Integer.parseInt(this.stripNonNumericCharacters(s));
28 | }
29 | else
30 | {
31 | this.decimalFormat = new DecimalFormat(pattern);
32 | this.intParser = s -> {
33 | try
34 | {
35 | return this.decimalFormat.parse(s.trim()).intValue();
36 | }
37 | catch (ParseException e)
38 | {
39 | throw exceptionByKey("CSV_PARSE_ERR")
40 | .with("type", "integer")
41 | .with("inputString", s)
42 | .get(e);
43 | }
44 | };
45 | }
46 | }
47 |
48 | public int parseAsInt(String aString)
49 | {
50 | if (aString == null || aString.isEmpty())
51 | {
52 | return 0;
53 | }
54 |
55 | return this.intParser.applyAsInt(aString);
56 | }
57 |
58 | public String format(int intValue)
59 | {
60 | return this.decimalFormat == null ? Integer.toString(intValue) : this.decimalFormat.format(intValue);
61 | }
62 |
63 | private String stripNonNumericCharacters(String s)
64 | {
65 | return this.nonNumericPattern.matcher(s).replaceAll("");
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/IntSchemaColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.DfColumn;
4 | import io.github.vmzakharov.ecdataframe.dataframe.DfIntColumn;
5 | import io.github.vmzakharov.ecdataframe.dataframe.DfIntColumnStored;
6 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
7 |
8 | public class IntSchemaColumn
9 | extends CsvSchemaColumn
10 | {
11 | final transient private IntFormatter intFormatter;
12 |
13 | public IntSchemaColumn(CsvSchema newCsvSchema, String newName, String newPattern)
14 | {
15 | super(newCsvSchema, newName, ValueType.INT, newPattern);
16 |
17 | this.intFormatter = new IntFormatter(this.getPattern());
18 | }
19 |
20 | @Override
21 | public String formatColumnValueAsString(DfColumn column, int rowIndex)
22 | {
23 | int intValue = ((DfIntColumn) column).getInt(rowIndex);
24 | return this.intFormatter.format(intValue);
25 | }
26 |
27 | @Override
28 | public void parseAndAddToColumn(String aString, DfColumn dfColumn)
29 | {
30 | if (aString == null)
31 | {
32 | dfColumn.addEmptyValue();
33 | return;
34 | }
35 |
36 | ((DfIntColumnStored) dfColumn).addInt(this.intFormatter.parseAsInt(aString), false);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/LongFormatter.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import org.eclipse.collections.api.block.function.primitive.LongFunction;
4 | import org.eclipse.collections.impl.utility.StringIterate;
5 |
6 | import java.text.DecimalFormat;
7 | import java.text.ParseException;
8 | import java.util.regex.Pattern;
9 |
10 | import static io.github.vmzakharov.ecdataframe.util.ExceptionFactory.exceptionByKey;
11 |
12 | public class LongFormatter
13 | {
14 | private DecimalFormat decimalFormat;
15 | private LongFunction longParser;
16 | private Pattern nonNumericPattern;
17 |
18 | public LongFormatter(String pattern)
19 | {
20 | if (StringIterate.isEmpty(pattern))
21 | {
22 | this.longParser = Long::parseLong;
23 | }
24 | else if (pattern.length() == 1)
25 | {
26 | this.nonNumericPattern = Pattern.compile("[^0-9" + pattern + "]");
27 | this.longParser = s -> Long.parseLong(this.stripNonNumericCharacters(s));
28 | }
29 | else
30 | {
31 | this.decimalFormat = new DecimalFormat(pattern);
32 | this.longParser = s -> {
33 | try
34 | {
35 | return this.decimalFormat.parse(s.trim()).longValue();
36 | }
37 | catch (ParseException e)
38 | {
39 | throw exceptionByKey("CSV_PARSE_ERR")
40 | .with("type", "integer")
41 | .with("inputString", s)
42 | .get(e);
43 | }
44 | };
45 | }
46 | }
47 |
48 | public long parseAsLong(String aString)
49 | {
50 | if (aString == null || aString.isEmpty())
51 | {
52 | return 0L;
53 | }
54 |
55 | return this.longParser.applyAsLong(aString);
56 | }
57 |
58 | public String format(long longValue)
59 | {
60 | return this.decimalFormat == null ? Long.toString(longValue) : this.decimalFormat.format(longValue);
61 | }
62 |
63 | private String stripNonNumericCharacters(String s)
64 | {
65 | return this.nonNumericPattern.matcher(s).replaceAll("");
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/LongSchemaColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.DfColumn;
4 | import io.github.vmzakharov.ecdataframe.dataframe.DfLongColumn;
5 | import io.github.vmzakharov.ecdataframe.dataframe.DfLongColumnStored;
6 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
7 |
8 | public class LongSchemaColumn
9 | extends CsvSchemaColumn
10 | {
11 | final transient private LongFormatter longFormatter;
12 |
13 | public LongSchemaColumn(CsvSchema newCsvSchema, String newName, String newPattern)
14 | {
15 | super(newCsvSchema, newName, ValueType.LONG, newPattern);
16 |
17 | this.longFormatter = new LongFormatter(this.getPattern());
18 | }
19 |
20 | @Override
21 | public String formatColumnValueAsString(DfColumn column, int rowIndex)
22 | {
23 | long longValue = ((DfLongColumn) column).getLong(rowIndex);
24 | return this.longFormatter.format(longValue);
25 | }
26 |
27 | @Override
28 | public void parseAndAddToColumn(String aString, DfColumn dfColumn)
29 | {
30 | if (aString == null)
31 | {
32 | dfColumn.addEmptyValue();
33 | return;
34 | }
35 |
36 | ((DfLongColumnStored) dfColumn).addLong(this.longFormatter.parseAsLong(aString), false);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dataset/StringSchemaColumn.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataset;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.DfColumn;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
5 |
6 | public class StringSchemaColumn
7 | extends CsvSchemaColumn
8 | {
9 | public StringSchemaColumn(CsvSchema newCsvSchema, String newName, String newPattern)
10 | {
11 | super(newCsvSchema, newName, ValueType.STRING, newPattern);
12 | }
13 |
14 | @Override
15 | public String formatColumnValueAsString(DfColumn column, int rowIndex)
16 | {
17 | String stringValue = column.getValueAsString(rowIndex);
18 | return this.csvSchema().getQuoteCharacter() + stringValue + this.csvSchema().getQuoteCharacter();
19 | }
20 |
21 | @Override
22 | public void parseAndAddToColumn(String aString, DfColumn dfColumn)
23 | {
24 | dfColumn.addObject(this.stripQuotesIfAny(aString));
25 | }
26 |
27 | private String stripQuotesIfAny(String aString)
28 | {
29 | if (aString == null || !this.csvSchema().surroundedByQuotes(aString))
30 | {
31 | return aString;
32 | }
33 |
34 | return aString.substring(1, aString.length() - 1);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/AbstractScript.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import org.eclipse.collections.api.list.ListIterable;
4 | import org.eclipse.collections.api.list.MutableList;
5 | import org.eclipse.collections.impl.factory.Lists;
6 |
7 | /**
8 | * An abstract superclass for the {@code Script} hierarchy, adds behavior to keep track of the script's expressions
9 | * (statements)
10 | */
11 | abstract public class AbstractScript
12 | implements Script
13 | {
14 | private final MutableList expressions = Lists.mutable.of();
15 |
16 | @Override
17 | public Expression addExpression(Expression anExpression)
18 | {
19 | this.expressions.add(anExpression);
20 | return anExpression;
21 | }
22 |
23 | @Override
24 | public ListIterable getExpressions()
25 | {
26 | return this.expressions;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/AliasExpr.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 |
7 | public record AliasExpr(String alias, Expression expression)
8 | implements Expression
9 | {
10 |
11 | @Override
12 | public Value evaluate(ExpressionEvaluationVisitor evaluationVisitor)
13 | {
14 | return this.expression.evaluate(evaluationVisitor);
15 | }
16 |
17 | @Override
18 | public void accept(ExpressionVisitor visitor)
19 | {
20 | visitor.visitAliasExpr(this);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/AnonymousScript.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 | import org.eclipse.collections.api.map.MutableMap;
7 | import org.eclipse.collections.impl.factory.Maps;
8 |
9 | public class AnonymousScript
10 | extends AbstractScript
11 | {
12 | private final MutableMap functions = Maps.mutable.of();
13 |
14 | public AnonymousScript()
15 | {
16 | }
17 |
18 | @Override
19 | public Value evaluate(ExpressionEvaluationVisitor visitor)
20 | {
21 | return visitor.visitAnonymousScriptExpr(this);
22 | }
23 |
24 | @Override
25 | public void accept(ExpressionVisitor visitor)
26 | {
27 | visitor.visitAnonymousScriptExpr(this);
28 | }
29 |
30 | public void addFunctionScript(FunctionScript functionScript)
31 | {
32 | this.functions.put(functionScript.getNormalizedName(), functionScript);
33 | }
34 |
35 | public MutableMap getFunctions()
36 | {
37 | return this.functions;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/AssignExpr.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 |
7 | public record AssignExpr(String varName, boolean isEscaped, Expression expression)
8 | implements Expression
9 | {
10 | @Override
11 | public Value evaluate(ExpressionEvaluationVisitor visitor)
12 | {
13 | return visitor.visitAssignExpr(this);
14 | }
15 |
16 | @Override
17 | public void accept(ExpressionVisitor visitor)
18 | {
19 | visitor.visitAssignExpr(this);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/BinaryExpr.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 |
7 | public record BinaryExpr(Expression operand1, Expression operand2, BinaryOp operation)
8 | implements Expression
9 | {
10 |
11 | @Override
12 | public Value evaluate(ExpressionEvaluationVisitor visitor)
13 | {
14 | return visitor.visitBinaryExpr(this);
15 | }
16 |
17 | @Override
18 | public void accept(ExpressionVisitor visitor)
19 | {
20 | visitor.visitBinaryExpr(this);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/BinaryOp.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 |
5 | import java.util.function.Supplier;
6 |
7 | /**
8 | * A binary operation in the expression DSL
9 | */
10 | public interface BinaryOp
11 | {
12 | /**
13 | * Applies this operation to the operands
14 | * @param operand1 the first operand
15 | * @param operand2 the second operand
16 | * @return the result of applying this operation
17 | */
18 | Value apply(Value operand1, Value operand2);
19 |
20 | /**
21 | * Override this method if partial evaluation of operands is possible to determine the outcome of the operation,
22 | * e.g. "and" and "or" operators.
23 | * @param operand1 a supplier of the first value
24 | * @param operand2 a supplier of the second value
25 | * @return the result of applying the operation
26 | */
27 | default Value apply(Supplier operand1, Supplier operand2)
28 | {
29 | return this.apply(operand1.get(), operand2.get());
30 | }
31 |
32 | /**
33 | * The parseable string representation of this operation parseable
34 | * @return the string representation of this operation
35 | */
36 | String asString();
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/ContainsOp.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.BooleanValue;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.VectorValue;
6 |
7 | public interface ContainsOp
8 | extends PredicateOp
9 | {
10 | ContainsOp IN = new ContainsOp()
11 | {
12 | @Override
13 | public BooleanValue applyWithVector(Value value, VectorValue vectorValue)
14 | {
15 | return BooleanValue.valueOf(vectorValue.getElements().anySatisfy(e -> ComparisonOp.EQ.apply(e, value).isTrue()));
16 | }
17 |
18 | @Override
19 | public BooleanValue applyString(String operand1, String operand2)
20 | {
21 | return BooleanValue.valueOf(operand2.contains(operand1));
22 | }
23 |
24 | @Override
25 | public String asString()
26 | {
27 | return "in";
28 | }
29 | };
30 |
31 | ContainsOp NOT_IN = new ContainsOp()
32 | {
33 | @Override
34 | public BooleanValue applyWithVector(Value value, VectorValue vectorValue)
35 | {
36 | return BooleanValue.valueOf(vectorValue.getElements().allSatisfy(e -> ComparisonOp.NE.apply(e, value).isTrue()));
37 | }
38 |
39 | @Override
40 | public BooleanValue applyString(String operand1, String operand2)
41 | {
42 | return BooleanValue.valueOf(!operand2.contains(operand1));
43 | }
44 |
45 | @Override
46 | public String asString()
47 | {
48 | return "not in";
49 | }
50 | };
51 |
52 | @Override
53 | default BooleanValue apply(Value operand1, Value operand2)
54 | {
55 | if (operand2.isVector())
56 | {
57 | return this.applyWithVector(operand1, (VectorValue) operand2);
58 | }
59 | return operand1.applyPredicate(operand2, this);
60 | }
61 |
62 | BooleanValue applyWithVector(Value value, VectorValue vectorValue);
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/DecimalExpr.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 |
7 | public record DecimalExpr(Expression unscaledValueExpr, Expression scaleExpr)
8 | implements Expression
9 | {
10 |
11 | @Override
12 | public Value evaluate(ExpressionEvaluationVisitor evaluationVisitor)
13 | {
14 | return evaluationVisitor.visitDecimalExpr(this);
15 | }
16 |
17 | @Override
18 | public void accept(ExpressionVisitor visitor)
19 | {
20 | visitor.visitDecimalExpr(this);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/EvalContext.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataset.HierarchicalDataSet;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
5 | import org.eclipse.collections.api.RichIterable;
6 | import org.eclipse.collections.api.map.MapIterable;
7 | import org.eclipse.collections.api.map.MutableMap;
8 |
9 | import java.time.LocalDate;
10 |
11 | public interface EvalContext
12 | {
13 | Value setVariable(String newVarName, Value newValue);
14 |
15 | Value getVariable(String newVariableName);
16 |
17 | Value getVariableOrDefault(String newVariableName, Value defaultValue);
18 |
19 | boolean hasVariable(String variableName);
20 |
21 | void removeVariable(String variableName);
22 |
23 | MapIterable getDeclaredFunctions();
24 |
25 | void setDeclaredFunctions(MutableMap newDeclaredFunctions);
26 |
27 | FunctionScript getDeclaredFunction(String functionName);
28 |
29 | void addDataSet(HierarchicalDataSet dataSet);
30 |
31 | HierarchicalDataSet getDataSet(String dataSetName);
32 |
33 | RichIterable getVariableNames();
34 |
35 | void removeAllVariables();
36 |
37 | String getString(String variableName);
38 |
39 | long getLong(String variableName);
40 |
41 | LocalDate getDate(String variableName);
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/EvalContextAbstract.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.DateValue;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.LongValue;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
6 | import org.eclipse.collections.api.map.MapIterable;
7 | import org.eclipse.collections.api.map.MutableMap;
8 | import org.eclipse.collections.impl.factory.Maps;
9 |
10 | import java.time.LocalDate;
11 |
12 | import static io.github.vmzakharov.ecdataframe.util.ExceptionFactory.exceptionByKey;
13 |
14 | abstract public class EvalContextAbstract
15 | implements EvalContext
16 | {
17 | private MutableMap declaredFunctions = Maps.mutable.of();
18 | private final MutableMap contextVariables = Maps.mutable.of();
19 |
20 | @Override
21 | public boolean hasVariable(String variableName)
22 | {
23 | return this.contextVariables.containsKey(variableName);
24 | }
25 |
26 | @Override
27 | public void removeVariable(String variableName)
28 | {
29 | this.contextVariables.remove(variableName);
30 | }
31 |
32 | @Override
33 | public void removeAllVariables()
34 | {
35 | this.contextVariables.clear();
36 | }
37 |
38 | protected MutableMap getContextVariables()
39 | {
40 | return this.contextVariables;
41 | }
42 |
43 | @Override
44 | public Value setVariable(String variableName, Value newValue)
45 | {
46 | if (this.hasVariable(variableName))
47 | {
48 | exceptionByKey("DSL_VAR_IMMUTABLE").with("variableName", variableName).fire();
49 | }
50 |
51 | this.getContextVariables().put(variableName, newValue);
52 | return newValue;
53 | }
54 |
55 | @Override
56 | public MapIterable getDeclaredFunctions()
57 | {
58 | return this.declaredFunctions;
59 | }
60 |
61 | @Override
62 | public void setDeclaredFunctions(MutableMap newDeclaredFunctions)
63 | {
64 | this.declaredFunctions = newDeclaredFunctions;
65 | }
66 |
67 | @Override
68 | public FunctionScript getDeclaredFunction(String functionName)
69 | {
70 | return this.declaredFunctions.get(functionName);
71 | }
72 |
73 | // helps avoid recursion
74 | public void loadFunctionsExcept(MapIterable functionsFromOutside, String nameToExclude)
75 | {
76 | functionsFromOutside.forEachKeyValue((k, v) -> {
77 | if (!k.equals(nameToExclude))
78 | {
79 | this.declaredFunctions.put(k, v);
80 | }
81 | });
82 | }
83 |
84 | @Override
85 | public String getString(String variableName)
86 | {
87 | return this.getVariable(variableName).stringValue();
88 | }
89 |
90 | @Override
91 | public long getLong(String variableName)
92 | {
93 | return ((LongValue) this.getVariable(variableName)).longValue();
94 | }
95 |
96 | @Override
97 | public LocalDate getDate(String variableName)
98 | {
99 | return ((DateValue) this.getVariable(variableName)).dateValue();
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/Expression.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 |
7 | public interface Expression
8 | {
9 | Value evaluate(ExpressionEvaluationVisitor evaluationVisitor);
10 |
11 | void accept(ExpressionVisitor visitor);
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/FunctionCallExpr.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 | import org.eclipse.collections.api.list.ListIterable;
7 | import org.eclipse.collections.impl.factory.Lists;
8 |
9 | public record FunctionCallExpr(String functionName, String normalizedFunctionName, ListIterable parameters)
10 | implements Expression
11 | {
12 | public FunctionCallExpr(String functionName, ListIterable parameters)
13 | {
14 | this(functionName, functionName.toUpperCase(), parameters);
15 | }
16 |
17 | public FunctionCallExpr(String newFunctionName)
18 | {
19 | this(newFunctionName, Lists.immutable.of());
20 | }
21 |
22 | @Override
23 | public Value evaluate(ExpressionEvaluationVisitor visitor)
24 | {
25 | return visitor.visitFunctionCallExpr(this);
26 | }
27 |
28 | @Override
29 | public void accept(ExpressionVisitor visitor)
30 | {
31 | visitor.visitFunctionCallExpr(this);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/FunctionDescriptor.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import org.eclipse.collections.api.list.ListIterable;
4 |
5 | public interface FunctionDescriptor
6 | {
7 | String getName();
8 |
9 | ListIterable getParameterNames();
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/FunctionScript.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 | import org.eclipse.collections.api.list.ListIterable;
7 |
8 | public class FunctionScript
9 | extends AbstractScript
10 | implements FunctionDescriptor
11 | {
12 | private final String name;
13 | private final String normalizedName;
14 |
15 | private final ListIterable parameterNames;
16 |
17 | public FunctionScript(String newName, ListIterable newParameterNames)
18 | {
19 | this.name = newName;
20 | this.normalizedName = this.name.toUpperCase();
21 | this.parameterNames = newParameterNames;
22 | }
23 |
24 | @Override
25 | public String getName()
26 | {
27 | return this.name;
28 | }
29 |
30 | public String getNormalizedName()
31 | {
32 | return this.normalizedName;
33 | }
34 |
35 | @Override
36 | public void accept(ExpressionVisitor visitor)
37 | {
38 | visitor.visitFunctionScriptExpr(this);
39 | }
40 |
41 | @Override
42 | public Value evaluate(ExpressionEvaluationVisitor evaluationVisitor)
43 | {
44 | return evaluationVisitor.visitFunctionScriptExpr(this);
45 | }
46 |
47 | @Override
48 | public ListIterable getParameterNames()
49 | {
50 | return this.parameterNames;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/IfElseExpr.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 |
7 | public record IfElseExpr(Expression condition, Expression ifScript, Expression elseScript, boolean isTernary)
8 | implements Expression
9 | {
10 | public IfElseExpr(Expression condition, Expression ifScript, Expression elseScript)
11 | {
12 | this(condition, ifScript, elseScript, false);
13 | }
14 |
15 | public IfElseExpr(Expression condition, Script ifScript)
16 | {
17 | this(condition, ifScript, null, false);
18 | }
19 |
20 | public boolean hasElseSection()
21 | {
22 | return this.elseScript != null;
23 | }
24 |
25 | @Override
26 | public Value evaluate(ExpressionEvaluationVisitor evaluationVisitor)
27 | {
28 | return evaluationVisitor.visitIfElseExpr(this);
29 | }
30 |
31 | @Override
32 | public void accept(ExpressionVisitor visitor)
33 | {
34 | visitor.visitIfElseExpr(this);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/IndexExpr.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 |
7 | public record IndexExpr(Expression vectorExpr, Expression indexExpr)
8 | implements Expression
9 | {
10 |
11 | @Override
12 | public Value evaluate(ExpressionEvaluationVisitor evaluationVisitor)
13 | {
14 | return evaluationVisitor.visitIndexExpr(this);
15 | }
16 |
17 | @Override
18 | public void accept(ExpressionVisitor visitor)
19 | {
20 | visitor.visitIndexExpr(this);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/PredicateOp.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.BooleanValue;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
5 |
6 | import java.math.BigDecimal;
7 | import java.time.LocalDate;
8 | import java.time.LocalDateTime;
9 |
10 | import static io.github.vmzakharov.ecdataframe.util.ExceptionFactory.exceptionByKey;
11 |
12 | public interface PredicateOp
13 | extends BinaryOp
14 | {
15 | @Override
16 | default BooleanValue apply(Value operand1, Value operand2)
17 | {
18 | if (operand1.isVoid() || operand2.isVoid())
19 | {
20 | throw this.unsupportedOn("null values");
21 | }
22 |
23 | return operand1.applyPredicate(operand2, this);
24 | }
25 |
26 | default BooleanValue applyString(String operand1, String operand2)
27 | {
28 | throw this.unsupportedOn("strings");
29 | }
30 |
31 | default BooleanValue applyDecimal(BigDecimal operand1, BigDecimal operand2)
32 | {
33 | throw this.unsupportedOn("decimals");
34 | }
35 |
36 | default BooleanValue applyDate(LocalDate operand1, LocalDate operand2)
37 | {
38 | throw this.unsupportedOn("dates");
39 | }
40 |
41 | default BooleanValue applyDateTime(LocalDateTime operand1, LocalDateTime operand2)
42 | {
43 | throw this.unsupportedOn("datetime values");
44 | }
45 |
46 | default BooleanValue applyLong(long operand1, long operand2)
47 | {
48 | throw this.unsupportedOn("longs");
49 | }
50 |
51 | default BooleanValue applyDouble(double operand1, double operand2)
52 | {
53 | throw this.unsupportedOn("doubles");
54 | }
55 |
56 | default RuntimeException unsupportedOn(String type)
57 | {
58 | return exceptionByKey("DSL_OP_NOT_SUPPORTED")
59 | .with("operation", this.asString())
60 | .with("type", type)
61 | .getUnsupported();
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/ProjectionExpr.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 | import io.github.vmzakharov.ecdataframe.dsl.visitor.PrettyPrintVisitor;
7 | import org.eclipse.collections.api.list.ListIterable;
8 | import org.eclipse.collections.api.list.MutableList;
9 | import org.eclipse.collections.impl.factory.Lists;
10 |
11 | public record ProjectionExpr(
12 | ListIterable projectionElements,
13 | Expression whereClause,
14 | ListIterable elementNames,
15 | ListIterable projectionExpressions)
16 | implements Expression
17 | {
18 | public ProjectionExpr(ListIterable newProjectionElements)
19 | {
20 | this(newProjectionElements, null);
21 | }
22 |
23 | public ProjectionExpr(ListIterable projectionElements, Expression whereClause)
24 | {
25 | this(projectionElements, whereClause, Lists.mutable.empty(), Lists.mutable.empty());
26 |
27 | // need to update these properties but don't want to expose the mutable type in the record API
28 | // so the property is declared as "Iterable", which means we have to cast here to update it
29 | MutableList mElementNames = (MutableList) this.elementNames;
30 | MutableList mProjectionExpressions = (MutableList) this.projectionExpressions;
31 |
32 | for (int i = 0; i < this.projectionElements.size(); i++)
33 | {
34 | Expression element = this.projectionElements.get(i);
35 | if (element instanceof AliasExpr aliasExpr)
36 | {
37 | mElementNames.add(aliasExpr.alias());
38 | mProjectionExpressions.add(aliasExpr.expression());
39 | }
40 | else
41 | {
42 | mElementNames.add(PrettyPrintVisitor.exprToString(element));
43 | mProjectionExpressions.add(element);
44 | }
45 | }
46 | }
47 |
48 | @Override
49 | public Value evaluate(ExpressionEvaluationVisitor visitor)
50 | {
51 | return visitor.visitProjectionExpr(this);
52 | }
53 |
54 | @Override
55 | public void accept(ExpressionVisitor visitor)
56 | {
57 | visitor.visitProjectionExpr(this);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/PropertyPathExpr.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 | import org.eclipse.collections.api.list.ListIterable;
7 |
8 | public record PropertyPathExpr(ListIterable pathElements)
9 | implements Expression
10 | {
11 | @Override
12 | public Value evaluate(ExpressionEvaluationVisitor visitor)
13 | {
14 | return visitor.visitPropertyPathExpr(this);
15 | }
16 |
17 | @Override
18 | public void accept(ExpressionVisitor visitor)
19 | {
20 | visitor.visitPropertyPathExpr(this);
21 | }
22 |
23 | public String getEntityName()
24 | {
25 | return this.pathElements.getFirst();
26 | }
27 |
28 | public String getPropertyChainString()
29 | {
30 | return this.pathElements.drop(1).makeString(".");
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/Script.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import org.eclipse.collections.api.list.ListIterable;
4 |
5 | /**
6 | * A script is a sequence of one or more statements or expressions. The result of executing a script is the value of
7 | * the last statement (or the last standalone expression) that was executed in the script.
8 | */
9 | public interface Script
10 | extends Expression
11 | {
12 | /**
13 | * adds an expression to the script
14 | * @param anExpression an expression to be added to the script
15 | * @return the expression
16 | */
17 | Expression addExpression(Expression anExpression);
18 |
19 | /**
20 | * returns all the expressions from the script
21 | * @return a list of all the expressions in the script
22 | */
23 | ListIterable getExpressions();
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/SimpleEvalContext.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataset.HierarchicalDataSet;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
5 | import org.eclipse.collections.api.RichIterable;
6 | import org.eclipse.collections.api.map.MutableMap;
7 | import org.eclipse.collections.impl.factory.Maps;
8 |
9 | import static io.github.vmzakharov.ecdataframe.util.ExceptionFactory.exceptionByKey;
10 |
11 | public class SimpleEvalContext
12 | extends EvalContextAbstract
13 | {
14 | private final MutableMap dataSets = Maps.mutable.of();
15 |
16 | @Override
17 | public Value getVariable(String newVariableName)
18 | {
19 | Value value = this.getContextVariables().get(newVariableName);
20 |
21 | if (value == null)
22 | {
23 | exceptionByKey("DSL_VAR_UNINITIALIZED").with("variableName", newVariableName).fire();
24 | }
25 |
26 | return value;
27 | }
28 |
29 | @Override
30 | public Value getVariableOrDefault(String newVariableName, Value defaultValue)
31 | {
32 | Value value = this.getContextVariables().get(newVariableName);
33 |
34 | return (value == null) ? defaultValue : value;
35 | }
36 |
37 | @Override
38 | public void addDataSet(HierarchicalDataSet dataSet)
39 | {
40 | this.dataSets.put(dataSet.getName(), dataSet);
41 | }
42 |
43 | @Override
44 | public HierarchicalDataSet getDataSet(String dataSetName)
45 | {
46 | return this.dataSets.get(dataSetName);
47 | }
48 |
49 | @Override
50 | public RichIterable getVariableNames()
51 | {
52 | return this.getContextVariables().keysView();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/StatementSequenceScript.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 |
7 | public class StatementSequenceScript
8 | extends AbstractScript
9 | {
10 |
11 | @Override
12 | public Value evaluate(ExpressionEvaluationVisitor evaluationVisitor)
13 | {
14 | return evaluationVisitor.visitStatementSequenceScriptExpr(this);
15 | }
16 |
17 | @Override
18 | public void accept(ExpressionVisitor visitor)
19 | {
20 | visitor.visitStatementSequenceScript(this);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/UnaryExpr.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 |
7 | public record UnaryExpr(UnaryOp operation, Expression operand)
8 | implements Expression
9 | {
10 |
11 | @Override
12 | public Value evaluate(ExpressionEvaluationVisitor evaluationVisitor)
13 | {
14 | return evaluationVisitor.visitUnaryExpr(this);
15 | }
16 |
17 | @Override
18 | public void accept(ExpressionVisitor visitor)
19 | {
20 | visitor.visitUnaryExpr(this);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/VarExpr.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 |
7 | public record VarExpr(String variableName, boolean isEscaped)
8 | implements Expression
9 | {
10 |
11 | @Override
12 | public Value evaluate(ExpressionEvaluationVisitor visitor)
13 | {
14 | return visitor.visitVarExpr(this);
15 | }
16 |
17 | @Override
18 | public void accept(ExpressionVisitor visitor)
19 | {
20 | visitor.visitVarExpr(this);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/VectorExpr.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
4 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionEvaluationVisitor;
5 | import io.github.vmzakharov.ecdataframe.dsl.visitor.ExpressionVisitor;
6 | import org.eclipse.collections.api.list.ListIterable;
7 |
8 | public record VectorExpr(ListIterable elements)
9 | implements Expression
10 | {
11 |
12 | @Override
13 | public Value evaluate(ExpressionEvaluationVisitor evaluationVisitor)
14 | {
15 | return evaluationVisitor.visitVectorExpr(this);
16 | }
17 |
18 | @Override
19 | public void accept(ExpressionVisitor visitor)
20 | {
21 | visitor.visitVectorExpr(this);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/function/IntrinsicFunctionDescriptorBuilder.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.function;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.EvalContext;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
6 | import org.eclipse.collections.api.list.ListIterable;
7 | import org.eclipse.collections.impl.factory.Lists;
8 |
9 | import java.util.function.Function;
10 |
11 | public class IntrinsicFunctionDescriptorBuilder
12 | extends IntrinsicFunctionDescriptor
13 | {
14 | private Function action = ignore -> Value.VOID;
15 | private Function, ValueType> returnTypeFunction = ignore -> ValueType.VOID;
16 |
17 | public IntrinsicFunctionDescriptorBuilder(String newName)
18 | {
19 | super(newName);
20 | }
21 |
22 | public IntrinsicFunctionDescriptorBuilder action(Function newAction)
23 | {
24 | this.action = newAction;
25 | return this;
26 | }
27 |
28 | public IntrinsicFunctionDescriptorBuilder parameterNames(ListIterable parameterNames)
29 | {
30 | this.setParameterNames(parameterNames);
31 | return this;
32 | }
33 |
34 | public IntrinsicFunctionDescriptorBuilder parameterNames(String... parameterNames)
35 | {
36 | return this.parameterNames(Lists.immutable.of(parameterNames));
37 | }
38 |
39 | public IntrinsicFunctionDescriptorBuilder returnType(ValueType newReturnType)
40 | {
41 | this.returnType(ignore -> newReturnType);
42 | return this;
43 | }
44 |
45 | public IntrinsicFunctionDescriptorBuilder returnType(Function, ValueType> newReturnTypeFunction)
46 | {
47 | this.returnTypeFunction = newReturnTypeFunction;
48 | return this;
49 | }
50 |
51 | @Override
52 | public Value evaluate(EvalContext context)
53 | {
54 | return this.action.apply(context);
55 | }
56 |
57 | @Override
58 | public ValueType returnType(ListIterable parameterTypes)
59 | {
60 | return this.returnTypeFunction.apply(parameterTypes);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/value/DataFrameValue.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.value;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.DataFrame;
4 |
5 | import static io.github.vmzakharov.ecdataframe.util.ExceptionFactory.exceptionByKey;
6 |
7 | public record DataFrameValue(DataFrame dataFrame)
8 | implements Value
9 | {
10 | public DataFrameValue
11 | {
12 | this.throwExceptionIfNull(dataFrame);
13 | }
14 |
15 | @Override
16 | public String asStringLiteral()
17 | {
18 | return "DataFrame [" + this.dataFrame.getName() + ", rows: " + this.dataFrame.rowCount() + ", columns: " + this.dataFrame.columnCount() + "] ";
19 | }
20 |
21 | @Override
22 | public ValueType getType()
23 | {
24 | return ValueType.DATA_FRAME;
25 | }
26 |
27 | @Override
28 | public String stringValue()
29 | {
30 | return this.dataFrame.asCsvString();
31 | }
32 |
33 | @Override
34 | public int compareTo(Value o)
35 | {
36 | throw exceptionByKey("DSL_DF_COMPARE_UNSUPPORTED").getUnsupported();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/value/DateTimeValue.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.value;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.PredicateOp;
4 | import io.github.vmzakharov.ecdataframe.dsl.UnaryOp;
5 |
6 | import java.time.LocalDateTime;
7 | import java.time.format.DateTimeFormatter;
8 |
9 | public record DateTimeValue(LocalDateTime value)
10 | implements Value
11 | {
12 | static private final DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_DATE_TIME;
13 |
14 | public DateTimeValue
15 | {
16 | this.throwExceptionIfNull(value);
17 | }
18 |
19 | @Override
20 | public String asStringLiteral()
21 | {
22 | return this.value.format(this.getFormatter());
23 | }
24 |
25 | @Override
26 | public Value apply(UnaryOp operation)
27 | {
28 | return operation.applyDateTime(this.value);
29 | }
30 |
31 | @Override
32 | public BooleanValue applyPredicate(Value another, PredicateOp operation)
33 | {
34 | return operation.applyDateTime(this.dateTimeValue(), ((DateTimeValue) another).dateTimeValue());
35 | }
36 |
37 | private DateTimeFormatter getFormatter()
38 | {
39 | return FORMATTER;
40 | }
41 |
42 | @Override
43 | public ValueType getType()
44 | {
45 | return ValueType.DATE_TIME;
46 | }
47 |
48 | public LocalDateTime dateTimeValue()
49 | {
50 | return this.value;
51 | }
52 |
53 | @Override
54 | public int compareTo(Value other)
55 | {
56 | this.checkSameTypeForComparison(other);
57 | return other.isVoid() ? 1 : this.dateTimeValue().compareTo(((DateTimeValue) other).dateTimeValue());
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/value/DateValue.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.value;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.PredicateOp;
4 | import io.github.vmzakharov.ecdataframe.dsl.UnaryOp;
5 |
6 | import java.time.LocalDate;
7 | import java.time.format.DateTimeFormatter;
8 |
9 | public record DateValue(LocalDate value)
10 | implements Value
11 | {
12 | static private final DateTimeFormatter FORMATTER = DateTimeFormatter.ISO_DATE;
13 |
14 | public DateValue
15 | {
16 | this.throwExceptionIfNull(value);
17 | }
18 |
19 | @Override
20 | public String asStringLiteral()
21 | {
22 | return this.value.format(this.getFormatter());
23 | }
24 |
25 | @Override
26 | public Value apply(UnaryOp operation)
27 | {
28 | return operation.applyDate(this.value);
29 | }
30 |
31 | @Override
32 | public BooleanValue applyPredicate(Value another, PredicateOp operation)
33 | {
34 | return operation.applyDate(this.dateValue(), ((DateValue) another).dateValue());
35 | }
36 |
37 | private DateTimeFormatter getFormatter()
38 | {
39 | return FORMATTER;
40 | }
41 |
42 | @Override
43 | public ValueType getType()
44 | {
45 | return ValueType.DATE;
46 | }
47 |
48 | public LocalDate dateValue()
49 | {
50 | return this.value;
51 | }
52 |
53 | @Override
54 | public int compareTo(Value other)
55 | {
56 | this.checkSameTypeForComparison(other);
57 | return other.isVoid() ? 1 : this.dateValue().compareTo(((DateValue) other).dateValue());
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/value/DecimalValue.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.value;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.ArithmeticOp;
4 | import io.github.vmzakharov.ecdataframe.dsl.PredicateOp;
5 | import io.github.vmzakharov.ecdataframe.dsl.UnaryOp;
6 |
7 | import java.math.BigDecimal;
8 |
9 | import static io.github.vmzakharov.ecdataframe.util.ExceptionFactory.*;
10 |
11 | public record DecimalValue(BigDecimal value)
12 | implements NumberValue
13 | {
14 | public DecimalValue
15 | {
16 | this.throwExceptionIfNull(value);
17 | }
18 |
19 | public DecimalValue(long unscaledValue, int scale)
20 | {
21 | this(BigDecimal.valueOf(unscaledValue, scale));
22 | }
23 |
24 | @Override
25 | public String asStringLiteral()
26 | {
27 | return "[" + this.value.unscaledValue() + ',' + this.value.scale() + ']';
28 | }
29 |
30 | @Override
31 | public Value apply(Value another, ArithmeticOp operation)
32 | {
33 | return operation.applyDecimal(this.decimalValue(), ((NumberValue) another).decimalValue());
34 | }
35 |
36 | @Override
37 | public Value apply(UnaryOp operation)
38 | {
39 | return operation.applyDecimal(this.value);
40 | }
41 |
42 | @Override
43 | public BooleanValue applyPredicate(Value another, PredicateOp operation)
44 | {
45 | return operation.applyDecimal(this.decimalValue(), ((DecimalValue) another).decimalValue());
46 | }
47 |
48 | @Override
49 | public ValueType getType()
50 | {
51 | return ValueType.DECIMAL;
52 | }
53 |
54 | @Override
55 | public BigDecimal decimalValue()
56 | {
57 | return this.value;
58 | }
59 |
60 | @Override
61 | public double doubleValue()
62 | {
63 | throw exceptionByKey("DSL_NO_DEC_TO_FLOAT_CONVERSION").get();
64 | }
65 |
66 | @Override
67 | public int compareTo(Value other)
68 | {
69 | this.checkSameTypeForComparison(other);
70 |
71 | return other.isVoid() ? 1 : this.decimalValue().compareTo(((DecimalValue) other).decimalValue());
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/value/DoubleValue.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.value;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.ArithmeticOp;
4 | import io.github.vmzakharov.ecdataframe.dsl.PredicateOp;
5 | import io.github.vmzakharov.ecdataframe.dsl.UnaryOp;
6 |
7 | import java.math.BigDecimal;
8 |
9 | public record DoubleValue(double value)
10 | implements RealNumberValue
11 | {
12 | @Override
13 | public double doubleValue()
14 | {
15 | return this.value;
16 | }
17 |
18 | @Override
19 | public BigDecimal decimalValue()
20 | {
21 | return BigDecimal.valueOf(this.value);
22 | }
23 |
24 | @Override
25 | public String asStringLiteral()
26 | {
27 | return Double.toString(this.value);
28 | }
29 |
30 | @Override
31 | public Value apply(Value another, ArithmeticOp operation)
32 | {
33 | return operation.applyDouble(this.doubleValue(), ((NumberValue) another).doubleValue());
34 | }
35 |
36 | @Override
37 | public Value apply(UnaryOp operation)
38 | {
39 | return operation.applyDouble(this.value);
40 | }
41 |
42 | @Override
43 | public BooleanValue applyPredicate(Value another, PredicateOp operation)
44 | {
45 | return operation.applyDouble(this.doubleValue(), ((NumberValue) another).doubleValue());
46 | }
47 |
48 | @Override
49 | public ValueType getType()
50 | {
51 | return ValueType.DOUBLE;
52 | }
53 |
54 | @Override
55 | public int compareTo(Value other)
56 | {
57 | this.checkSameTypeForComparison(other);
58 | return other.isVoid() ? 1 : Double.compare(this.doubleValue(), ((DoubleValue) other).doubleValue());
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/value/FloatValue.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.value;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.ArithmeticOp;
4 | import io.github.vmzakharov.ecdataframe.dsl.PredicateOp;
5 | import io.github.vmzakharov.ecdataframe.dsl.UnaryOp;
6 |
7 | import java.math.BigDecimal;
8 |
9 | public record FloatValue(float value)
10 | implements RealNumberValue
11 | {
12 | public float floatValue()
13 | {
14 | return this.value;
15 | }
16 |
17 | @Override
18 | public double doubleValue()
19 | {
20 | return this.value;
21 | }
22 |
23 | @Override
24 | public BigDecimal decimalValue()
25 | {
26 | return BigDecimal.valueOf(this.value);
27 | }
28 |
29 | @Override
30 | public String asStringLiteral()
31 | {
32 | return Double.toString(this.value);
33 | }
34 |
35 | @Override
36 | public Value apply(Value another, ArithmeticOp operation)
37 | {
38 | return operation.applyDouble(this.doubleValue(), ((NumberValue) another).doubleValue());
39 | }
40 |
41 | @Override
42 | public Value apply(UnaryOp operation)
43 | {
44 | return operation.applyFloat(this.value);
45 | }
46 |
47 | @Override
48 | public BooleanValue applyPredicate(Value another, PredicateOp operation)
49 | {
50 | return operation.applyDouble(this.doubleValue(), ((NumberValue) another).doubleValue());
51 | }
52 |
53 | @Override
54 | public ValueType getType()
55 | {
56 | return ValueType.FLOAT;
57 | }
58 |
59 | @Override
60 | public int compareTo(Value other)
61 | {
62 | this.checkSameTypeForComparison(other);
63 | return other.isVoid() ? 1 : Float.compare(this.floatValue(), ((FloatValue) other).floatValue());
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/value/IntValue.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.value;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.ArithmeticOp;
4 | import io.github.vmzakharov.ecdataframe.dsl.PredicateOp;
5 | import io.github.vmzakharov.ecdataframe.dsl.UnaryOp;
6 |
7 | import java.math.BigDecimal;
8 |
9 | public record IntValue(int value)
10 | implements WholeNumberValue
11 | {
12 | @Override
13 | public String asStringLiteral()
14 | {
15 | return Integer.toString(this.value);
16 | }
17 |
18 | public int intValue()
19 | {
20 | return this.value;
21 | }
22 |
23 | @Override
24 | public double doubleValue()
25 | {
26 | return this.value;
27 | }
28 |
29 | @Override
30 | public long longValue()
31 | {
32 | return this.value;
33 | }
34 |
35 | @Override
36 | public BigDecimal decimalValue()
37 | {
38 | return BigDecimal.valueOf(this.value);
39 | }
40 |
41 | @Override
42 | public Value apply(Value another, ArithmeticOp operation)
43 | {
44 | if (another.isWholeNumber())
45 | {
46 | return operation.applyLong(this.longValue(), ((WholeNumberValue) another).longValue());
47 | }
48 |
49 | return operation.applyDouble(this.doubleValue(), ((NumberValue) another).doubleValue());
50 | }
51 |
52 | @Override
53 | public Value apply(UnaryOp operation)
54 | {
55 | return operation.applyInt(this.value);
56 | }
57 |
58 | @Override
59 | public BooleanValue applyPredicate(Value another, PredicateOp operation)
60 | {
61 | if (another.isWholeNumber())
62 | {
63 | return operation.applyLong(this.longValue(), ((WholeNumberValue) another).longValue());
64 | }
65 |
66 | return operation.applyDouble(this.doubleValue(), ((NumberValue) another).doubleValue());
67 | }
68 |
69 | @Override
70 | public ValueType getType()
71 | {
72 | return ValueType.INT;
73 | }
74 |
75 | @Override
76 | public int compareTo(Value other)
77 | {
78 | this.checkSameTypeForComparison(other);
79 | return other.isVoid() ? 1 : Integer.compare(this.intValue(), ((IntValue) other).intValue());
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/value/LongValue.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.value;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.ArithmeticOp;
4 | import io.github.vmzakharov.ecdataframe.dsl.PredicateOp;
5 | import io.github.vmzakharov.ecdataframe.dsl.UnaryOp;
6 |
7 | import java.math.BigDecimal;
8 |
9 | public record LongValue(long value)
10 | implements WholeNumberValue
11 | {
12 | @Override
13 | public String asStringLiteral()
14 | {
15 | return Long.toString(this.value);
16 | }
17 |
18 | @Override
19 | public long longValue()
20 | {
21 | return this.value;
22 | }
23 |
24 | @Override
25 | public double doubleValue()
26 | {
27 | return this.value;
28 | }
29 |
30 | @Override
31 | public BigDecimal decimalValue()
32 | {
33 | return BigDecimal.valueOf(this.value);
34 | }
35 |
36 | @Override
37 | public Value apply(Value another, ArithmeticOp operation)
38 | {
39 | if (another.isWholeNumber())
40 | {
41 | return operation.applyLong(this.longValue(), ((WholeNumberValue) another).longValue());
42 | }
43 |
44 | return operation.applyDouble(this.doubleValue(), ((NumberValue) another).doubleValue());
45 | }
46 |
47 | @Override
48 | public Value apply(UnaryOp operation)
49 | {
50 | return operation.applyLong(this.value);
51 | }
52 |
53 | @Override
54 | public BooleanValue applyPredicate(Value another, PredicateOp operation)
55 | {
56 | if (another.isDouble())
57 | {
58 | return operation.applyDouble(this.doubleValue(), ((DoubleValue) another).doubleValue());
59 | }
60 | return operation.applyLong(this.longValue(), ((LongValue) another).longValue());
61 | }
62 |
63 | @Override
64 | public ValueType getType()
65 | {
66 | return ValueType.LONG;
67 | }
68 |
69 | @Override
70 | public int compareTo(Value other)
71 | {
72 | this.checkSameTypeForComparison(other);
73 | return other.isVoid() ? 1 : Long.compare(this.longValue(), ((LongValue) other).longValue());
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/value/NumberValue.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.value;
2 |
3 | import java.math.BigDecimal;
4 |
5 | public interface NumberValue
6 | extends Value
7 | {
8 | double doubleValue();
9 |
10 | BigDecimal decimalValue();
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/value/RealNumberValue.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.value;
2 |
3 | public interface RealNumberValue
4 | extends NumberValue
5 | {
6 | }
7 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/value/StringValue.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.value;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.ArithmeticOp;
4 | import io.github.vmzakharov.ecdataframe.dsl.PredicateOp;
5 | import io.github.vmzakharov.ecdataframe.dsl.UnaryOp;
6 |
7 | public record StringValue(String value)
8 | implements Value
9 | {
10 | public StringValue
11 | {
12 | this.throwExceptionIfNull(value);
13 | }
14 |
15 | @Override
16 | public Value apply(Value another, ArithmeticOp operation)
17 | {
18 | return operation.applyString(this.stringValue(), another.stringValue());
19 | }
20 |
21 | @Override
22 | public Value apply(UnaryOp operation)
23 | {
24 | return operation.applyString(this.value);
25 | }
26 |
27 | @Override
28 | public String asStringLiteral()
29 | {
30 | return this.value.indexOf('\"') == -1 ? '"' + this.value + '"' : '\'' + this.value + '\'';
31 | }
32 |
33 | @Override
34 | public String stringValue()
35 | {
36 | return this.value;
37 | }
38 |
39 | @Override
40 | public BooleanValue applyPredicate(Value another, PredicateOp operation)
41 | {
42 | this.checkSameTypeForComparison(another);
43 | return operation.applyString(this.stringValue(), ((StringValue) another).stringValue());
44 | }
45 |
46 | @Override
47 | public ValueType getType()
48 | {
49 | return ValueType.STRING;
50 | }
51 |
52 | @Override
53 | public int compareTo(Value other)
54 | {
55 | this.checkSameTypeForComparison(other);
56 | return other.isVoid() ? 1 : this.stringValue().compareTo(other.stringValue());
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/value/ValueType.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.value;
2 |
3 | public enum ValueType
4 | {
5 | BOOLEAN, DOUBLE, FLOAT, LONG, INT, DECIMAL, STRING, DATE, DATE_TIME, VOID, VECTOR, DATA_FRAME;
6 |
7 | public boolean isVoid()
8 | {
9 | return this == VOID;
10 | }
11 |
12 | public boolean isBoolean()
13 | {
14 | return this == BOOLEAN;
15 | }
16 |
17 | public boolean isLong()
18 | {
19 | return this == LONG;
20 | }
21 |
22 | public boolean isInt()
23 | {
24 | return this == INT;
25 | }
26 |
27 | public boolean isDouble()
28 | {
29 | return this == DOUBLE;
30 | }
31 |
32 | public boolean isFloat()
33 | {
34 | return this == FLOAT;
35 | }
36 |
37 | public boolean isDecimal()
38 | {
39 | return this == DECIMAL;
40 | }
41 |
42 | public boolean isNumber()
43 | {
44 | return this == LONG || this == DOUBLE || this == INT || this == FLOAT || this == DECIMAL;
45 | }
46 |
47 | public boolean isWholeNumber()
48 | {
49 | return this == LONG || this == INT;
50 | }
51 |
52 | public boolean isRealNumber()
53 | {
54 | return this == DOUBLE || this == FLOAT;
55 | }
56 |
57 | public boolean isDate()
58 | {
59 | return this == DATE;
60 | }
61 |
62 | public boolean isDateTime()
63 | {
64 | return this == DATE_TIME;
65 | }
66 |
67 | public boolean isTemporal()
68 | {
69 | return this == DATE || this == DATE_TIME;
70 | }
71 |
72 | public boolean isString()
73 | {
74 | return this == STRING;
75 | }
76 |
77 | public boolean isVector()
78 | {
79 | return this == VECTOR;
80 | }
81 |
82 | public boolean isDataFrame()
83 | {
84 | return this == DATA_FRAME;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/value/VectorValue.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.value;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.UnaryOp;
4 | import org.eclipse.collections.api.list.ListIterable;
5 | import org.eclipse.collections.impl.factory.Lists;
6 |
7 | public record VectorValue(ListIterable elements)
8 | implements Value
9 | {
10 | public static final VectorValue EMPTY = new VectorValue(Lists.immutable.empty());
11 |
12 | @Override
13 | public String asStringLiteral()
14 | {
15 | return this.elements.makeString(Value::asStringLiteral, "(", ", ", ")");
16 | }
17 |
18 | @Override
19 | public ValueType getType()
20 | {
21 | return ValueType.VECTOR;
22 | }
23 |
24 | public ListIterable getElements()
25 | {
26 | return this.elements;
27 | }
28 |
29 | public int size()
30 | {
31 | return this.elements.size();
32 | }
33 |
34 | public Value get(int index)
35 | {
36 | return this.elements.get(index);
37 | }
38 |
39 | @Override
40 | public Value apply(UnaryOp operation)
41 | {
42 | return operation.applyVector(this.elements);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/value/WholeNumberValue.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.value;
2 |
3 | public interface WholeNumberValue
4 | extends NumberValue
5 | {
6 | long longValue();
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/visitor/ExpressionEvaluationVisitor.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.visitor;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.AnonymousScript;
4 | import io.github.vmzakharov.ecdataframe.dsl.AssignExpr;
5 | import io.github.vmzakharov.ecdataframe.dsl.BinaryExpr;
6 | import io.github.vmzakharov.ecdataframe.dsl.DecimalExpr;
7 | import io.github.vmzakharov.ecdataframe.dsl.FunctionCallExpr;
8 | import io.github.vmzakharov.ecdataframe.dsl.FunctionScript;
9 | import io.github.vmzakharov.ecdataframe.dsl.IfElseExpr;
10 | import io.github.vmzakharov.ecdataframe.dsl.IndexExpr;
11 | import io.github.vmzakharov.ecdataframe.dsl.ProjectionExpr;
12 | import io.github.vmzakharov.ecdataframe.dsl.PropertyPathExpr;
13 | import io.github.vmzakharov.ecdataframe.dsl.StatementSequenceScript;
14 | import io.github.vmzakharov.ecdataframe.dsl.UnaryExpr;
15 | import io.github.vmzakharov.ecdataframe.dsl.VarExpr;
16 | import io.github.vmzakharov.ecdataframe.dsl.VectorExpr;
17 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
18 |
19 | public interface ExpressionEvaluationVisitor
20 | {
21 | Value visitAssignExpr(AssignExpr expr);
22 |
23 | Value visitBinaryExpr(BinaryExpr expr);
24 |
25 | Value visitUnaryExpr(UnaryExpr expr);
26 |
27 | Value visitConstExpr(Value expr);
28 |
29 | Value visitFunctionCallExpr(FunctionCallExpr expr);
30 |
31 | Value visitIfElseExpr(IfElseExpr expr);
32 |
33 | Value visitPropertyPathExpr(PropertyPathExpr expr);
34 |
35 | Value visitAnonymousScriptExpr(AnonymousScript expr);
36 |
37 | Value visitFunctionScriptExpr(FunctionScript expr);
38 |
39 | Value visitStatementSequenceScriptExpr(StatementSequenceScript expr);
40 |
41 | Value visitVarExpr(VarExpr expr);
42 |
43 | Value visitProjectionExpr(ProjectionExpr expr);
44 |
45 | Value visitVectorExpr(VectorExpr expr);
46 |
47 | Value visitIndexExpr(IndexExpr expr);
48 |
49 | Value visitDecimalExpr(DecimalExpr expr);
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/dsl/visitor/ExpressionVisitor.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dsl.visitor;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.AliasExpr;
4 | import io.github.vmzakharov.ecdataframe.dsl.AnonymousScript;
5 | import io.github.vmzakharov.ecdataframe.dsl.AssignExpr;
6 | import io.github.vmzakharov.ecdataframe.dsl.BinaryExpr;
7 | import io.github.vmzakharov.ecdataframe.dsl.DecimalExpr;
8 | import io.github.vmzakharov.ecdataframe.dsl.FunctionCallExpr;
9 | import io.github.vmzakharov.ecdataframe.dsl.FunctionScript;
10 | import io.github.vmzakharov.ecdataframe.dsl.IfElseExpr;
11 | import io.github.vmzakharov.ecdataframe.dsl.IndexExpr;
12 | import io.github.vmzakharov.ecdataframe.dsl.ProjectionExpr;
13 | import io.github.vmzakharov.ecdataframe.dsl.PropertyPathExpr;
14 | import io.github.vmzakharov.ecdataframe.dsl.StatementSequenceScript;
15 | import io.github.vmzakharov.ecdataframe.dsl.UnaryExpr;
16 | import io.github.vmzakharov.ecdataframe.dsl.VarExpr;
17 | import io.github.vmzakharov.ecdataframe.dsl.VectorExpr;
18 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
19 |
20 | public interface ExpressionVisitor
21 | {
22 | void visitAliasExpr(AliasExpr expr);
23 |
24 | void visitAssignExpr(AssignExpr expr);
25 |
26 | void visitBinaryExpr(BinaryExpr expr);
27 |
28 | void visitUnaryExpr(UnaryExpr expr);
29 |
30 | void visitConstExpr(Value expr);
31 |
32 | void visitFunctionCallExpr(FunctionCallExpr expr);
33 |
34 | void visitIfElseExpr(IfElseExpr expr);
35 |
36 | void visitPropertyPathExpr(PropertyPathExpr expr);
37 |
38 | void visitAnonymousScriptExpr(AnonymousScript expr);
39 |
40 | void visitFunctionScriptExpr(FunctionScript expr);
41 |
42 | void visitStatementSequenceScript(StatementSequenceScript expr);
43 |
44 | void visitVarExpr(VarExpr expr);
45 |
46 | void visitProjectionExpr(ProjectionExpr expr);
47 |
48 | void visitVectorExpr(VectorExpr expr);
49 |
50 | void visitIndexExpr(IndexExpr expr);
51 |
52 | void visitDecimalExpr(DecimalExpr expr);
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/grammar/CollectingErrorListener.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.grammar;
2 |
3 | import org.antlr.v4.runtime.BaseErrorListener;
4 | import org.antlr.v4.runtime.RecognitionException;
5 | import org.antlr.v4.runtime.Recognizer;
6 | import org.antlr.v4.runtime.Token;
7 | import org.eclipse.collections.api.factory.Lists;
8 | import org.eclipse.collections.api.list.ListIterable;
9 | import org.eclipse.collections.api.list.MutableList;
10 |
11 | public class CollectingErrorListener
12 | extends BaseErrorListener
13 | {
14 | private final MutableList errors = Lists.mutable.of();
15 |
16 | @Override
17 | public void syntaxError(Recognizer, ?> recognizer,
18 | Object offendingSymbol,
19 | int line, int charPositionInLine,
20 | String msg,
21 | RecognitionException e)
22 | {
23 | this.errors.add(new Error(offendingSymbol, line, charPositionInLine, msg));
24 | }
25 |
26 | public ListIterable getErrors()
27 | {
28 | return this.errors;
29 | }
30 |
31 | public boolean hasErrors()
32 | {
33 | return this.errors.notEmpty();
34 | }
35 |
36 | public static class Error
37 | {
38 | private final Object offendingSymbol;
39 | private final int line;
40 | private final int charPositionInLine;
41 | private final String message;
42 |
43 | public Error(Object newOffendingSymbol, int newLine, int newCharPositionInLine, String newMessage)
44 | {
45 | this.offendingSymbol = newOffendingSymbol;
46 | this.line = newLine;
47 | this.charPositionInLine = newCharPositionInLine;
48 | this.message = newMessage;
49 | }
50 |
51 | public int line()
52 | {
53 | return this.line;
54 | }
55 |
56 | public int charPositionInLine()
57 | {
58 | return this.charPositionInLine;
59 | }
60 |
61 | public int tokenStartIndex()
62 | {
63 | return ((Token) this.offendingSymbol).getStartIndex();
64 | }
65 |
66 | public int tokenStopIndex()
67 | {
68 | return ((Token) this.offendingSymbol).getStopIndex();
69 | }
70 |
71 | public String detailedErrorMessage()
72 | {
73 | return "line " + this.line + ":" + this.charPositionInLine + " at " + this.offendingSymbol + ": " + this.message;
74 | }
75 |
76 | public String briefErrorMessage()
77 | {
78 | return "line " + this.line + ":" + this.charPositionInLine + " " + this.message;
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/util/CollectingPrinter.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.util;
2 |
3 | public class CollectingPrinter
4 | implements Printer
5 | {
6 | private final StringBuilder buffer = new StringBuilder();
7 |
8 | @Override
9 | public void print(String value)
10 | {
11 | this.buffer.append(value);
12 | }
13 |
14 | public String toString()
15 | {
16 | return this.buffer.toString();
17 | }
18 |
19 | public void clear()
20 | {
21 | this.buffer.setLength(0);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/util/Printer.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.util;
2 |
3 | public interface Printer
4 | {
5 | void print(String value);
6 |
7 | default void newLine()
8 | {
9 | this.print("\n");
10 | }
11 |
12 | default void println(String value)
13 | {
14 | this.print(value);
15 | this.newLine();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/util/PrinterFactory.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.util;
2 |
3 | final public class PrinterFactory
4 | {
5 | static private Printer printer = new SysOutPrinter();
6 | static private Printer errPrinter = new SysErrPrinter();
7 |
8 | private PrinterFactory()
9 | {
10 | // Utility class
11 | }
12 |
13 | public static Printer getPrinter()
14 | {
15 | return printer;
16 | }
17 |
18 | public static void setPrinter(Printer newPrinter)
19 | {
20 | printer = newPrinter;
21 | }
22 |
23 | public static Printer getErrPrinter()
24 | {
25 | return errPrinter;
26 | }
27 |
28 | public static void setErrPrinter(Printer newPrinter)
29 | {
30 | errPrinter = newPrinter;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/util/Stopwatch.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.util;
2 |
3 | public class Stopwatch
4 | {
5 | private long startTimeMillis;
6 | private long endTimeMillis;
7 |
8 | private long startUsedMemoryBytes;
9 | private long endUsedMemoryBytes;
10 |
11 | private long totalMemoryBytes;
12 | private long usedMemoryBytes;
13 | private long freeMemoryBytes;
14 |
15 | public void start()
16 | {
17 | this.recordMemoryUsage();
18 | this.startUsedMemoryBytes = this.usedMemoryBytes;
19 | this.startTimeMillis = System.currentTimeMillis();
20 | }
21 |
22 | public void stop()
23 | {
24 | this.endTimeMillis = System.currentTimeMillis();
25 | this.recordMemoryUsage();
26 | this.endUsedMemoryBytes = this.usedMemoryBytes;
27 | }
28 |
29 | public long elapsedTimeMillis()
30 | {
31 | return this.endTimeMillis - this.startTimeMillis;
32 | }
33 |
34 | public long usedMemoryChangeBytes()
35 | {
36 | return this.endUsedMemoryBytes - this.startUsedMemoryBytes;
37 | }
38 |
39 | public long totalMemoryBytes()
40 | {
41 | return this.totalMemoryBytes;
42 | }
43 |
44 | public long usedMemoryBytes()
45 | {
46 | return this.usedMemoryBytes;
47 | }
48 |
49 | public long freeMemoryBytes()
50 | {
51 | return this.freeMemoryBytes;
52 | }
53 |
54 | private void recordMemoryUsage()
55 | {
56 | System.gc();
57 | System.gc();
58 | System.gc();
59 | Runtime runtime = Runtime.getRuntime();
60 |
61 | this.freeMemoryBytes = runtime.freeMemory();
62 | this.totalMemoryBytes = runtime.totalMemory();
63 | this.usedMemoryBytes = this.totalMemoryBytes - this.freeMemoryBytes;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/util/SysErrPrinter.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.util;
2 |
3 | public class SysErrPrinter
4 | implements Printer
5 | {
6 | @Override
7 | public void print(String value)
8 | {
9 | System.err.print(value);
10 | }
11 |
12 | @Override
13 | public void newLine()
14 | {
15 | System.err.println();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/io/github/vmzakharov/ecdataframe/util/SysOutPrinter.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.util;
2 |
3 | public class SysOutPrinter
4 | implements Printer
5 | {
6 | @Override
7 | public void print(String value)
8 | {
9 | System.out.print(value);
10 | }
11 |
12 | @Override
13 | public void newLine()
14 | {
15 | System.out.println();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/test/java/io/github/vmzakharov/ecdataframe/AggregateFunctionTest.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dataframe.AggregateFunction;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
5 | import io.github.vmzakharov.ecdataframe.util.FormatWithPlaceholders;
6 | import org.eclipse.collections.api.list.ListIterable;
7 | import org.eclipse.collections.impl.factory.Lists;
8 | import org.junit.jupiter.api.Test;
9 |
10 | import static org.junit.jupiter.api.Assertions.*;
11 |
12 | public class AggregateFunctionTest
13 | {
14 | @Test
15 | public void testClone()
16 | {
17 | AggregateFunction sum = AggregateFunction.sum("Foo", "Bar");
18 | AggregateFunction cloned = sum.cloneWith("Baz", "Qux");
19 |
20 | assertEquals("Baz", cloned.getSourceColumnName());
21 | assertEquals("Qux", cloned.getTargetColumnName());
22 | assertEquals(sum.getClass(), cloned.getClass());
23 | }
24 |
25 | @Test
26 | public void testFailureToClone()
27 | {
28 | AggregateFunction wontClone = new CloneResistant();
29 |
30 | Exception exception = assertThrows(
31 | RuntimeException.class,
32 | () -> wontClone.cloneWith("Baz", "Qux")
33 | );
34 |
35 | assertEquals(
36 | FormatWithPlaceholders
37 | .messageFromKey("AGG_CANNOT_CLONE")
38 | .with("operation", wontClone.getName())
39 | .toString(),
40 | exception.getMessage()
41 | );
42 | }
43 |
44 | private static class CloneResistant
45 | extends AggregateFunction
46 | {
47 | public CloneResistant()
48 | {
49 | super("ABC", "XYZ");
50 | }
51 |
52 | @Override
53 | public ListIterable supportedSourceTypes()
54 | {
55 | return Lists.immutable.of(ValueType.STRING);
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/test/java/io/github/vmzakharov/ecdataframe/DateExpressionTest.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import java.time.LocalDate;
6 |
7 | import static org.junit.jupiter.api.Assertions.assertEquals;
8 | import static org.junit.jupiter.api.Assertions.assertFalse;
9 | import static org.junit.jupiter.api.Assertions.assertTrue;
10 |
11 | public class DateExpressionTest
12 | {
13 | @Test
14 | public void parseDate()
15 | {
16 | LocalDate date = ExpressionTestUtil.evaluateToDate("toDate(\"2020-02-15\")");
17 | assertEquals(LocalDate.of(2020, 2, 15), date);
18 | }
19 |
20 | @Test
21 | public void dateProximity()
22 | {
23 | assertTrue(ExpressionTestUtil.evaluateToBoolean("withinDays(toDate(\"2020-02-15\"), toDate(\"2020-02-17\"), 3)"));
24 | assertFalse(ExpressionTestUtil.evaluateToBoolean("withinDays(toDate(\"2020-02-11\"), toDate(\"2020-02-17\"), 3)"));
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/test/java/io/github/vmzakharov/ecdataframe/FunctionDeclarationsTest.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.LongValue;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
5 |
6 | import org.junit.jupiter.api.Test;
7 |
8 | import static org.junit.jupiter.api.Assertions.*;
9 |
10 | public class FunctionDeclarationsTest
11 | {
12 | @Test
13 | public void simpleFunction()
14 | {
15 | String scriptText = """
16 | function x (a, b)
17 | {
18 | z = a - b
19 | a + b
20 | }
21 |
22 | y = 2
23 | x(5, y * 7)""";
24 |
25 | Value result = ExpressionTestUtil.evaluateScript(scriptText);
26 | assertTrue(result.isLong());
27 | assertEquals(19, ((LongValue) result).longValue());
28 | }
29 |
30 | @Test
31 | public void manyFunctions()
32 | {
33 | String scriptText = """
34 | function sum(a, b)
35 | {
36 | a + b
37 | }
38 |
39 | function mul(a, b)
40 | {
41 | a * b
42 | }
43 |
44 | one = 1
45 | two = 2
46 | sum( mul(5, two), SUM(one, two) )""";
47 |
48 | Value result = ExpressionTestUtil.evaluateScript(scriptText);
49 | assertTrue(result.isLong());
50 | assertEquals(13, ((LongValue) result).longValue());
51 | }
52 |
53 | @Test
54 | public void noArgFunction()
55 | {
56 | String scriptText = """
57 | function hello
58 | {
59 | "hello"
60 | }
61 |
62 | function bang
63 | {
64 | "!"
65 | }
66 |
67 | hello() + " there" + bang()""";
68 |
69 | Value result = ExpressionTestUtil.evaluateScript(scriptText);
70 | assertTrue(result.isString());
71 | assertEquals("hello there!", result.stringValue());
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/test/java/io/github/vmzakharov/ecdataframe/HandcraftedExpressionTreeTest.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.ArithmeticOp;
4 | import io.github.vmzakharov.ecdataframe.dsl.BinaryExpr;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.DoubleValue;
6 | import io.github.vmzakharov.ecdataframe.dsl.value.LongValue;
7 | import io.github.vmzakharov.ecdataframe.dsl.value.StringValue;
8 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
9 | import io.github.vmzakharov.ecdataframe.dsl.visitor.InMemoryEvaluationVisitor;
10 |
11 | import org.junit.jupiter.api.BeforeEach;
12 | import org.junit.jupiter.api.Test;
13 |
14 | import static org.junit.jupiter.api.Assertions.*;
15 |
16 | public class HandcraftedExpressionTreeTest
17 | {
18 | private InMemoryEvaluationVisitor evaluationVisitor;
19 |
20 | @BeforeEach
21 | public void setEvalContext()
22 | {
23 | this.evaluationVisitor = new InMemoryEvaluationVisitor();
24 | }
25 |
26 | @Test
27 | public void intAddition()
28 | {
29 | Value result = new BinaryExpr(
30 | new LongValue(123),
31 | new LongValue(456),
32 | ArithmeticOp.ADD
33 | ).evaluate(this.evaluationVisitor);
34 |
35 | assertEquals(579, ((LongValue) result).longValue());
36 | }
37 |
38 | @Test
39 | public void doubleAddition()
40 | {
41 | Value result = new BinaryExpr(
42 | new DoubleValue(123.321),
43 | new DoubleValue(456.025),
44 | ArithmeticOp.ADD
45 | ).evaluate(this.evaluationVisitor);
46 |
47 | assertEquals(579.346, ((DoubleValue) result).doubleValue(), 0.0000000001);
48 | }
49 |
50 | @Test
51 | public void stringAddition()
52 | {
53 | Value result = new BinaryExpr(
54 | new StringValue("Oompa"),
55 | new StringValue("Loompa"),
56 | ArithmeticOp.ADD
57 | ).evaluate(this.evaluationVisitor);
58 |
59 | assertEquals("OompaLoompa", result.stringValue());
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/test/java/io/github/vmzakharov/ecdataframe/ImmutableVariablesTest.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.util.FormatWithPlaceholders;
4 | import org.junit.jupiter.api.Assertions;
5 | import org.junit.jupiter.api.Test;
6 |
7 | import static org.junit.jupiter.api.Assertions.assertThrows;
8 |
9 | public class ImmutableVariablesTest
10 | {
11 | @Test
12 | public void immutableVariables()
13 | {
14 | Exception exception = assertThrows(
15 | RuntimeException.class,
16 | () -> ExpressionTestUtil.evaluateScript(
17 | "a = 1\n"
18 | + "a = 2")
19 | );
20 |
21 | Assertions.assertEquals(
22 | FormatWithPlaceholders.messageFromKey("DSL_VAR_IMMUTABLE").with("variableName", "a").toString(),
23 | exception.getMessage()
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/test/java/io/github/vmzakharov/ecdataframe/IsEmptyOperationTest.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.SimpleEvalContext;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
5 |
6 | import org.junit.jupiter.api.Test;
7 |
8 | import static io.github.vmzakharov.ecdataframe.ExpressionTestUtil.scriptEvaluatesToFalse;
9 | import static io.github.vmzakharov.ecdataframe.ExpressionTestUtil.scriptEvaluatesToTrue;
10 | import static org.junit.jupiter.api.Assertions.*;
11 |
12 | public class IsEmptyOperationTest
13 | {
14 | @Test
15 | public void stringIsEmptyOrNot()
16 | {
17 | scriptEvaluatesToFalse("\"Foo\" is empty");
18 | scriptEvaluatesToFalse("\"Foo\" is empty or \"Bar\" is empty");
19 |
20 | scriptEvaluatesToTrue("\"Foo\" is not empty");
21 | scriptEvaluatesToTrue("\"Foo\" is not empty and 2 > 1");
22 |
23 | scriptEvaluatesToTrue("\"\" is empty");
24 | scriptEvaluatesToFalse("\"\" is not empty");
25 |
26 | scriptEvaluatesToTrue("\"Foo\" is not empty and \"\" is empty");
27 | }
28 |
29 | @Test
30 | public void dateIsEmptyOrNot()
31 | {
32 | scriptEvaluatesToFalse("toDate(\"2020-10-06\") is empty");
33 | scriptEvaluatesToFalse("toDate(\"2020-10-06\") is empty or \"Bar\" is empty");
34 |
35 | scriptEvaluatesToTrue("toDate(\"2020-10-06\") is not empty");
36 | }
37 |
38 | @Test
39 | public void vectorIsEmptyOrNot()
40 | {
41 | scriptEvaluatesToFalse("(1, 2, 3) is empty");
42 | scriptEvaluatesToFalse("(1, 2, 3) is empty or \"Bar\" is empty");
43 |
44 | scriptEvaluatesToTrue("(1, 2, 3) is not empty");
45 |
46 | scriptEvaluatesToTrue("() is empty");
47 | scriptEvaluatesToFalse("() is not empty");
48 | }
49 |
50 | @Test
51 | public void voidValueIsNull()
52 | {
53 | SimpleEvalContext context = new SimpleEvalContext();
54 | context.setVariable("x", Value.VOID);
55 |
56 | scriptEvaluatesToTrue("x is null", context);
57 | scriptEvaluatesToFalse("x is not null", context);
58 | }
59 |
60 | @Test
61 | public void voidValueNotIsNotEmpty()
62 | {
63 | SimpleEvalContext context = new SimpleEvalContext();
64 | context.setVariable("x", Value.VOID);
65 |
66 | assertThrows(
67 | UnsupportedOperationException.class,
68 | () -> scriptEvaluatesToFalse("x is not empty", context)
69 | );
70 | }
71 |
72 | @Test
73 | public void voidValueNotIsEmpty()
74 | {
75 | SimpleEvalContext context = new SimpleEvalContext();
76 | context.setVariable("x", Value.VOID);
77 |
78 | assertThrows(
79 | UnsupportedOperationException.class,
80 | () -> scriptEvaluatesToFalse("x is empty", context)
81 | );
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/test/java/io/github/vmzakharov/ecdataframe/TypeInferenceForBuiltInFunctionsTest.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.EvalContext;
4 | import io.github.vmzakharov.ecdataframe.dsl.function.BuiltInFunctions;
5 | import io.github.vmzakharov.ecdataframe.dsl.function.IntrinsicFunctionDescriptor;
6 | import io.github.vmzakharov.ecdataframe.dsl.value.LongValue;
7 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
8 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
9 | import org.eclipse.collections.api.list.ListIterable;
10 | import org.junit.jupiter.api.Test;
11 |
12 | import static io.github.vmzakharov.ecdataframe.TypeInferenceUtil.assertScriptType;
13 |
14 | public class TypeInferenceForBuiltInFunctionsTest
15 | {
16 | @Test
17 | public void abs()
18 | {
19 | assertScriptType("abs(5)", ValueType.LONG);
20 | assertScriptType("abs(1.23)", ValueType.DOUBLE);
21 | }
22 |
23 | @Test
24 | public void startswith()
25 | {
26 | assertScriptType("startsWith('ABCD', 'AB')", ValueType.BOOLEAN);
27 | }
28 |
29 | @Test
30 | public void contains()
31 | {
32 | assertScriptType("contains('ABCD', 'AB')", ValueType.BOOLEAN);
33 | }
34 |
35 | @Test
36 | public void toUpper()
37 | {
38 | assertScriptType("toUpper('ABCD')", ValueType.STRING);
39 | }
40 |
41 | @Test
42 | public void substr()
43 | {
44 | assertScriptType("substr('ABCD', 2)", ValueType.STRING);
45 | assertScriptType("substr('ABCD', 1, 2)", ValueType.STRING);
46 | }
47 |
48 | @Test
49 | public void toStringFunction()
50 | {
51 | assertScriptType("toString('ABCD')", ValueType.STRING);
52 | assertScriptType("toString(123)", ValueType.STRING);
53 | assertScriptType("toString(12.34)", ValueType.STRING);
54 | assertScriptType("toString(toDate(2020, 10, 25))", ValueType.STRING);
55 | }
56 |
57 | @Test
58 | public void toLong()
59 | {
60 | assertScriptType("toLong('123')", ValueType.LONG);
61 | }
62 |
63 | @Test
64 | public void toDobule()
65 | {
66 | assertScriptType("toDouble('456')", ValueType.DOUBLE);
67 | }
68 |
69 | @Test
70 | public void toDate()
71 | {
72 | assertScriptType("toDate(2001, 11, 22)", ValueType.DATE);
73 | }
74 |
75 | @Test
76 | public void toDateTime()
77 | {
78 | assertScriptType("toDateTime(2001, 11, 22, 10, 10, 10)", ValueType.DATE_TIME);
79 | }
80 |
81 | @Test
82 | public void functionAddedAtRuntime()
83 | {
84 | BuiltInFunctions.addFunctionDescriptor(new IntrinsicFunctionDescriptor("two")
85 | {
86 | @Override
87 | public Value evaluate(EvalContext context)
88 | {
89 | return new LongValue(2);
90 | }
91 |
92 | @Override
93 | public ValueType returnType(ListIterable parameterTypes)
94 | {
95 | return ValueType.LONG;
96 | }
97 | });
98 |
99 | assertScriptType("two()", ValueType.LONG);
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/test/java/io/github/vmzakharov/ecdataframe/TypeInferenceUtil.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.EvalContext;
4 | import io.github.vmzakharov.ecdataframe.dsl.Expression;
5 | import io.github.vmzakharov.ecdataframe.dsl.SimpleEvalContext;
6 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
7 | import io.github.vmzakharov.ecdataframe.dsl.visitor.TypeInferenceVisitor;
8 | import org.junit.jupiter.api.Assertions;
9 |
10 | final public class TypeInferenceUtil
11 | {
12 | private TypeInferenceUtil()
13 | {
14 | // utility class
15 | }
16 |
17 | public static void assertScriptType(String scriptAsString, ValueType valueType)
18 | {
19 | assertScriptType(scriptAsString, new SimpleEvalContext(), valueType);
20 | }
21 |
22 | public static void assertScriptType(String scriptAsString, EvalContext context, ValueType valueType)
23 | {
24 | Expression expression = ExpressionTestUtil.toScript(scriptAsString);
25 | TypeInferenceVisitor visitor = new TypeInferenceVisitor(context);
26 | expression.accept(visitor);
27 | Assertions.assertEquals(valueType, visitor.getLastExpressionType());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/test/java/io/github/vmzakharov/ecdataframe/VectorExpressionTest.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.BooleanValue;
4 | import io.github.vmzakharov.ecdataframe.dsl.value.LongValue;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.Value;
6 | import org.junit.jupiter.api.Test;
7 |
8 | import static org.junit.jupiter.api.Assertions.*;
9 |
10 | public class VectorExpressionTest
11 | {
12 | @Test
13 | public void vectorVariableIn()
14 | {
15 | Value result = ExpressionTestUtil.evaluateScript(
16 | """
17 | x = ("a", "b", "c")
18 | y = "a"
19 | y in x
20 | """
21 | );
22 |
23 | assertTrue(((BooleanValue) result).isTrue());
24 | }
25 |
26 | @Test
27 | public void index()
28 | {
29 | assertEquals(2L, ExpressionTestUtil.evaluateToLong("(1, 2, 3)[1]"));
30 | }
31 |
32 | @Test
33 | public void indexWithVariables()
34 | {
35 | Value result = ExpressionTestUtil.evaluateScript(
36 | """
37 | x = ("a", "b", "c")
38 | y = 2
39 | x[y]
40 | """
41 | );
42 |
43 | assertEquals("c", result.stringValue());
44 | }
45 |
46 | @Test
47 | public void indexWithFunction()
48 | {
49 | Value result = ExpressionTestUtil.evaluateScript(
50 | """
51 | function foo(switch)
52 | {
53 | if switch == 1 then
54 | (1, 2, 3)
55 | else
56 | (4, 5, 6)
57 | endif
58 | }
59 |
60 | foo(2)[2] + foo(1)[1]\s"""
61 | );
62 |
63 | assertEquals(8L, ((LongValue) result).longValue());
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/test/java/io/github/vmzakharov/ecdataframe/dataframe/ColumnIteratorTest.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import org.junit.jupiter.api.BeforeEach;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import static org.junit.jupiter.api.Assertions.*;
7 |
8 | public class ColumnIteratorTest
9 | {
10 | private DataFrame dataFrame;
11 |
12 | @BeforeEach
13 | public void setupDataFrame()
14 | {
15 | this.dataFrame = new DataFrame("Test")
16 | .addStringColumn("Name").addStringColumn("Quux").addStringColumn("Waldo")
17 | .addRow("Alice", "A", "A")
18 | .addRow("Bob", "B", "A")
19 | .addRow("Carl", "C", null)
20 | .addRow("Doris", "D", "B")
21 | ;
22 | }
23 |
24 | @Test
25 | public void injectInto()
26 | {
27 | int totalStringLength = this.dataFrame.getStringColumn("Name")
28 | .injectIntoBreakOnNulls(
29 | 0,
30 | (len, s) -> len + s.length()
31 | );
32 |
33 | assertEquals(17, totalStringLength);
34 | }
35 |
36 | @Test
37 | public void injectIntoWithBreakOnNullResult()
38 | {
39 | Integer totalStringLength = this.dataFrame.getStringColumn("Quux")
40 | .injectIntoBreakOnNulls(
41 | 0,
42 | (len, s) -> {
43 | if (s.equals("C"))
44 | {
45 | fail("Shouldn't reach C");
46 | }
47 |
48 | return s.equals("B") ? null : len + s.length();
49 | }
50 | );
51 |
52 | assertNull(totalStringLength);
53 | }
54 |
55 | @Test
56 | public void injectIntoWithBreakOnNullValue()
57 | {
58 | Integer totalStringLength = this.dataFrame.getStringColumn("Waldo")
59 | .injectIntoBreakOnNulls(
60 | 0,
61 | (len, s) -> {
62 | if (!s.equals("A"))
63 | {
64 | fail("Shouldn't get here");
65 | }
66 |
67 | return len + s.length();
68 | }
69 | );
70 |
71 | assertNull(totalStringLength);
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/test/java/io/github/vmzakharov/ecdataframe/dataframe/DataFrameAggregationErrorMessageTest.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.dsl.value.ValueType;
4 | import io.github.vmzakharov.ecdataframe.util.FormatWithPlaceholders;
5 | import org.eclipse.collections.api.list.ListIterable;
6 | import org.eclipse.collections.impl.factory.Lists;
7 |
8 | import org.junit.jupiter.api.Assertions;
9 | import org.junit.jupiter.api.BeforeEach;
10 | import org.junit.jupiter.api.Test;
11 |
12 | import java.time.LocalDate;
13 |
14 | import static org.junit.jupiter.api.Assertions.*;
15 |
16 | public class DataFrameAggregationErrorMessageTest
17 | {
18 | private DataFrame dataFrame;
19 |
20 | @BeforeEach
21 | public void initialiseDataFrame()
22 | {
23 | this.dataFrame = new DataFrame("FrameOfData")
24 | .addStringColumn("Name").addStringColumn("Foo").addLongColumn("Bar").addDoubleColumn("Baz")
25 | .addIntColumn("Waldo").addDateColumn("Corge")
26 | .addRow("Alice", "Abc", 123L, 10.0, 100, LocalDate.of(2023, 10, 21))
27 | .addRow("Bob", "Def", 456L, 12.0, -25, LocalDate.of(2024, 11, 22))
28 | .addRow("Carol", "Xyz", -789L, 17.0, 42, LocalDate.of(2025, 12, 23));
29 | }
30 |
31 | @Test
32 | public void aggString()
33 | {
34 | this.checkAggMessage("Name", "string");
35 | }
36 |
37 | @Test
38 | public void aggLong()
39 | {
40 | this.checkAggMessage("Bar", "long");
41 | }
42 |
43 | @Test
44 | public void aggDouble()
45 | {
46 | this.checkAggMessage("Baz", "double");
47 | }
48 |
49 | @Test
50 | public void aggInt()
51 | {
52 | this.checkAggMessage("Waldo", "int");
53 | }
54 |
55 | @Test
56 | public void aggDate()
57 | {
58 | this.checkAggMessage("Corge", "date");
59 | }
60 |
61 | public void checkAggMessage(String columnName, String columnType)
62 | {
63 | AggregateFunction aggregator = new BadAggregation(columnName);
64 |
65 | Exception e = Assertions.assertThrows(UnsupportedOperationException.class, () -> this.dataFrame.aggregate(Lists.immutable.of(aggregator)));
66 |
67 | assertEquals(
68 | FormatWithPlaceholders.messageFromKey("AGG_COL_TYPE_UNSUPPORTED")
69 | .with("operation", aggregator.getName())
70 | .with("operationDescription", aggregator.getDescription())
71 | .with("columnName", columnName)
72 | .with("columnType", columnType)
73 | .toString(),
74 | e.getMessage());
75 | }
76 |
77 | private static class BadAggregation
78 | extends AggregateFunction
79 | {
80 | public BadAggregation(String newColumnName)
81 | {
82 | super(newColumnName);
83 | }
84 |
85 | @Override
86 | public ListIterable supportedSourceTypes()
87 | {
88 | return Lists.immutable.of(ValueType.STRING, ValueType.LONG);
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/test/java/io/github/vmzakharov/ecdataframe/dataframe/DataFrameExpressionTest.java:
--------------------------------------------------------------------------------
1 | package io.github.vmzakharov.ecdataframe.dataframe;
2 |
3 | import io.github.vmzakharov.ecdataframe.ExpressionTestUtil;
4 | import io.github.vmzakharov.ecdataframe.dsl.Expression;
5 | import io.github.vmzakharov.ecdataframe.dsl.value.LongValue;
6 | import org.eclipse.collections.api.factory.Lists;
7 | import org.eclipse.collections.api.list.ImmutableList;
8 | import org.eclipse.collections.api.list.primitive.MutableLongList;
9 | import org.eclipse.collections.impl.factory.primitive.LongLists;
10 | import org.eclipse.collections.impl.list.primitive.IntInterval;
11 |
12 | import org.junit.jupiter.api.BeforeEach;
13 | import org.junit.jupiter.api.Test;
14 |
15 | import static org.junit.jupiter.api.Assertions.*;
16 |
17 | public class DataFrameExpressionTest
18 | {
19 | private DataFrame df;
20 |
21 | @BeforeEach
22 | public void initializeDataFrame()
23 | {
24 | this.df = new DataFrame("this.df1")
25 | .addStringColumn("Name").addLongColumn("Count").addDoubleColumn("Value");
26 |
27 | this.df
28 | .addRow("Alice", 5, 23.45)
29 | .addRow("Bob", 10, 12.34)
30 | .addRow("Carol", 11, 56.78)
31 | .addRow("Dan", 0, 7.89);
32 | }
33 |
34 | @Test
35 | public void arithmeticExpression()
36 | {
37 | Expression expression = ExpressionTestUtil.toExpression("Count * 2");
38 |
39 | MutableLongList values = LongLists.mutable.of();
40 |
41 | IntInterval.zeroTo(3)
42 | .collectLong(i -> {
43 | this.df.setEvalContextRowIndex(i);
44 | return ((LongValue) expression.evaluate(this.df.getEvalVisitor())).longValue();
45 | }
46 | , values
47 | );
48 |
49 | assertEquals(LongLists.immutable.of(10, 20, 22, 0), values);
50 | }
51 |
52 | @Test
53 | public void stringExpression()
54 | {
55 | Expression expression = ExpressionTestUtil.toExpression("substr(Name, 2) + \"X\"");
56 |
57 | ImmutableList