@@ -8,15 +8,16 @@ import org.jetbrains.kotlinx.dataframe.columns.ColumnSet
8
8
import org.jetbrains.kotlinx.dataframe.columns.ColumnWithPath
9
9
import org.jetbrains.kotlinx.dataframe.columns.ColumnsResolver
10
10
import org.jetbrains.kotlinx.dataframe.columns.SingleColumn
11
+ import org.jetbrains.kotlinx.dataframe.columns.UnresolvedColumnsPolicy
11
12
import org.jetbrains.kotlinx.dataframe.columns.toColumnSet
12
13
import org.jetbrains.kotlinx.dataframe.documentation.LineBreak
13
14
import org.jetbrains.kotlinx.dataframe.documentation.UsageTemplateColumnsSelectionDsl.UsageTemplate
14
15
import org.jetbrains.kotlinx.dataframe.impl.aggregation.toColumns
15
- import org.jetbrains.kotlinx.dataframe.impl.columns.addParentPath
16
16
import org.jetbrains.kotlinx.dataframe.impl.columns.allColumnsExceptAndUnpack
17
17
import org.jetbrains.kotlinx.dataframe.impl.columns.allColumnsExceptKeepingStructure
18
18
import org.jetbrains.kotlinx.dataframe.impl.columns.changePath
19
19
import org.jetbrains.kotlinx.dataframe.impl.columns.createColumnSet
20
+ import org.jetbrains.kotlinx.dataframe.impl.columns.isMissingColumn
20
21
import org.jetbrains.kotlinx.dataframe.impl.columns.transformSingle
21
22
import org.jetbrains.kotlinx.dataframe.impl.getColumnsWithPaths
22
23
import kotlin.reflect.KProperty
@@ -215,10 +216,10 @@ public interface AllExceptColumnsSelectionDsl<out T> {
215
216
// region SingleColumn
216
217
217
218
public infix fun <C > SingleColumn<DataRow<C>>.allColsExcept (selector : ColumnsSelector <C , * >): ColumnSet <* > =
218
- allColsExceptInternal(selector.toColumns(), false )
219
+ allColsExceptInternal(selector.toColumns())
219
220
220
221
public infix fun SingleColumn <DataRow <* >>.allColsExcept (other : ColumnsResolver <* >): ColumnSet <* > =
221
- allColsExceptInternal(other, true )
222
+ allColsExceptInternal(other)
222
223
223
224
public fun SingleColumn <DataRow <* >>.allColsExcept (vararg other : ColumnsResolver <* >): ColumnSet <* > =
224
225
allColsExcept(other.toColumnSet())
@@ -235,11 +236,12 @@ public interface AllExceptColumnsSelectionDsl<out T> {
235
236
public fun SingleColumn <DataRow <* >>.allColsExcept (vararg others : KProperty <* >): ColumnSet <* > =
236
237
allColsExcept(others.toColumnSet())
237
238
238
- public infix fun SingleColumn <DataRow <* >>.allColsExcept (other : ColumnPath ): ColumnSet <* > =
239
- allColsExcept(column<Any ?>(other))
239
+ // reference and path
240
+ public infix fun SingleColumn <DataRow <* >>.allColsExcept (other : ColumnReference <* >): ColumnSet <* > =
241
+ allColsExceptInternal(other)
240
242
241
- public fun SingleColumn <DataRow <* >>.allColsExcept (vararg others : ColumnPath ): ColumnSet <* > =
242
- allColsExcept(others.toColumnSet() )
243
+ public fun SingleColumn <DataRow <* >>.allColsExcept (vararg other : ColumnReference < * > ): ColumnSet <* > =
244
+ allColsExceptInternal( * other )
243
245
244
246
// endregion
245
247
@@ -266,11 +268,11 @@ public interface AllExceptColumnsSelectionDsl<out T> {
266
268
public fun String.allColsExcept (vararg others : KProperty <* >): ColumnSet <* > =
267
269
allColsExcept(others.toColumnSet())
268
270
269
- public fun String.allColsExcept (other : ColumnPath ): ColumnSet <* > =
271
+ public fun String.allColsExcept (other : ColumnReference < * > ): ColumnSet <* > =
270
272
columnGroup(this ).allColsExcept(other)
271
273
272
- public fun String.allColsExcept (vararg others : ColumnPath ): ColumnSet <* > =
273
- allColsExcept(others.toColumnSet() )
274
+ public fun String.allColsExcept (vararg others : ColumnReference < * > ): ColumnSet <* > =
275
+ columnGroup( this ).allColsExcept( * others )
274
276
275
277
// endregion
276
278
@@ -297,11 +299,11 @@ public interface AllExceptColumnsSelectionDsl<out T> {
297
299
public fun KProperty <* >.allColsExcept (vararg others : KProperty <* >): ColumnSet <* > =
298
300
allColsExcept(others.toColumnSet())
299
301
300
- public infix fun KProperty <* >.allColsExcept (other : ColumnPath ): ColumnSet <* > =
302
+ public infix fun KProperty <* >.allColsExcept (other : ColumnReference < * > ): ColumnSet <* > =
301
303
columnGroup(this ).allColsExcept(other)
302
304
303
- public fun KProperty <* >.allColsExcept (vararg others : ColumnPath ): ColumnSet <* > =
304
- allColsExcept(others.toColumnSet() )
305
+ public fun KProperty <* >.allColsExcept (vararg others : ColumnReference < * > ): ColumnSet <* > =
306
+ columnGroup( this ).allColsExcept( * others )
305
307
306
308
// endregion
307
309
@@ -328,44 +330,91 @@ public interface AllExceptColumnsSelectionDsl<out T> {
328
330
public fun ColumnPath.allColsExcept (vararg others : KProperty <* >): ColumnSet <* > =
329
331
allColsExcept(others.toColumnSet())
330
332
331
- public infix fun ColumnPath.allColsExcept (other : ColumnPath ): ColumnSet <* > =
333
+ public infix fun ColumnPath.allColsExcept (other : ColumnReference < * > ): ColumnSet <* > =
332
334
columnGroup(this ).allColsExcept(other)
333
335
334
- public fun ColumnPath.allColsExcept (vararg others : ColumnPath ): ColumnSet <* > =
335
- allColsExcept(others.toColumnSet() )
336
+ public fun ColumnPath.allColsExcept (vararg others : ColumnReference < * > ): ColumnSet <* > =
337
+ columnGroup( this ).allColsExcept( * others )
336
338
337
339
// endregion
338
340
339
341
// endregion
340
342
341
- private fun SingleColumn <DataRow <* >>.allColsExceptInternal (other : ColumnsResolver <* >, allowFullPaths : Boolean ) =
343
+ /* *
344
+ * streamlines column references such that both relative and absolute paths can be used
345
+ */
346
+ // TODO remove this overload again
347
+ private fun SingleColumn <DataRow <* >>.allColsExceptInternal (vararg others : ColumnReference <* >): ColumnSet <* > =
348
+ allColsExceptInternal(others.toColumnSet())
349
+ // transformSingleWithContext { col ->
350
+ // val correctedOthers = others.map {
351
+ // it.path().dropStartWrt(col.path)
352
+ // }
353
+ // allColsExceptInternal(correctedOthers.toColumnSet()).resolve(this)
354
+ // }
355
+
356
+ private fun SingleColumn <DataRow <* >>.allColsExceptInternal (other : ColumnsResolver <* >) =
342
357
createColumnSet { context ->
343
- this .ensureIsColumnGroup().resolveSingle(context)?.let { col ->
344
- require(col.isColumnGroup()) {
345
- " Column ${col.path} is not a ColumnGroup and can thus not be excepted from."
358
+ val col = this .ensureIsColumnGroup().resolveSingle(context)
359
+ ? : return @createColumnSet emptyList()
360
+ val colGroup = col.asColumnGroup()
361
+ val colPath = col.path
362
+
363
+ val parentScope = (this @AllExceptColumnsSelectionDsl as ColumnsSelectionDsl <T >)
364
+ .asSingleColumn()
365
+ val parentCol = parentScope.ensureIsColumnGroup().resolveSingle(context)
366
+ ? : return @createColumnSet emptyList()
367
+ val parentColGroup = parentCol.asColumnGroup()
368
+ val parentPath = parentCol.path
369
+
370
+ val allCols = colGroup.getColumnsWithPaths { all() }
371
+
372
+ val colsToExceptRelativeToParent = parentColGroup
373
+ .getColumnsWithPaths(UnresolvedColumnsPolicy .Skip ) { other }
374
+
375
+
376
+ val colsToExceptRelativeToCol = colGroup
377
+ .getColumnsWithPaths(UnresolvedColumnsPolicy .Skip ) { other }
378
+
379
+ // throw exceptions for columns that weren't in this or parent scope
380
+ (colsToExceptRelativeToParent + colsToExceptRelativeToCol).groupBy { it.path }
381
+ .forEach { (path, cols) ->
382
+ if (cols.all { it.data.isMissingColumn() }) {
383
+ throw IllegalArgumentException (
384
+ " Column ${(colPath + path).joinToString()} and ${(parentPath + path).joinToString()} not found."
385
+ )
386
+ }
346
387
}
347
388
348
- val allCols = col.asColumnGroup()
349
- .getColumnsWithPaths { all() }
350
-
351
- // try to resolve all columns to except relative to the current column
352
- try {
353
- val columnsToExcept = col.asColumnGroup()
354
- .getColumnsWithPaths(context.unresolvedColumnsPolicy) { other }
355
-
356
- allCols.allColumnsExceptKeepingStructure(columnsToExcept)
357
- .map { it.changePath(col.path + it.path) }
358
- } catch (e: IllegalStateException ) {
359
- // if allowed, attempt to resole all columns to except absolutely too if relative failed
360
- if (allowFullPaths) {
361
- val allColsAbsolute = allCols.map { it.addParentPath(col.path) }
362
- val columnsToExcept = other.resolve(context)
363
- allColsAbsolute.allColumnsExceptKeepingStructure(columnsToExcept)
364
- } else {
365
- throw e
366
- }
389
+ val colsToExcept = colsToExceptRelativeToCol +
390
+ colsToExceptRelativeToParent.map { // adjust the path to be relative to the current column
391
+ it.changePath(it.path.dropFirst(colPath.size - parentPath.size))
367
392
}
368
- } ? : emptyList()
393
+
394
+ allCols.allColumnsExceptKeepingStructure(
395
+ colsToExcept
396
+ .distinctBy { it.path }
397
+ .filterNot { it.data.isMissingColumn() }
398
+ ).map { it.changePath(col.path + it.path) }
399
+
400
+ // try to resolve all columns to except relative to the current column
401
+ // try {
402
+ // val columnsToExcept = colGroup
403
+ // .getColumnsWithPaths(context.unresolvedColumnsPolicy) { other }
404
+ //
405
+ // allCols.allColumnsExceptKeepingStructure(columnsToExcept)
406
+ // .map { it.changePath(col.path + it.path) }
407
+ // } catch (e: IllegalStateException) {
408
+ // // if allowed, attempt to resole all columns to except absolutely too if relative failed
409
+ // if (allowFullPaths) {
410
+ // val allColsAbsolute = allCols.map { it.addParentPath(col.path) }
411
+ // val columnsToExcept = other.resolve(context)
412
+ // allColsAbsolute.allColumnsExceptKeepingStructure(columnsToExcept)
413
+ // } else {
414
+ // throw e
415
+ // }
416
+ // }
417
+
369
418
}
370
419
}
371
420
0 commit comments