Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add better naming and CFML interop with CFML Arrays and Structs #8

Merged
merged 1 commit into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 45 additions & 2 deletions models/Stream.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,14 @@ component accessors="true" {
return variables.jStream.toArray();
}

/**
* Returns an array containing the elements of this stream.
* Right now, an alias of toArray(), with the hope that we can convert the `toArray` to a CFML array in the future.
*/
function toNativeArray(){
return variables.jStream.toArray();
}


/**
* Returns the count of elements in this stream.
Expand Down Expand Up @@ -787,6 +795,17 @@ component accessors="true" {
return variables.jStream.collect( variables.Collectors.toList() );
}

/**
* A mutable reduction operation that accumulates input elements into a mutable result container, optionally transforming the accumulated result into a final representation after all input elements have been processed.
* By default we will collect to a CFML array.
*
* This is a terminal operation.
*
*/
function collectAsArray(){
return arraySlice( variables.jStream.collect( variables.Collectors.toList() ), 1 );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure with 1 it works in Java arrays? and not 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it does. It is mostly used to convert the Java array to a CFML array.

}

/**
* Returns a Collector implementing a "group by" operation on input elements, grouping elements according to a
* classification function, and returning the results in a struct according to the classifier function
Expand Down Expand Up @@ -919,7 +938,7 @@ component accessors="true" {
}

/**
* Collect the items to a struct. Please be sure to map the appropriate key and value identifiers
* Collect the items to a HashMap. Please be sure to map the appropriate key and value identifiers
*
* NOTE: the struct type will only work if the collection we are collecting is a struct or an object
* This is a terminal operation.
Expand All @@ -928,7 +947,7 @@ component accessors="true" {
* @valueID If using struct, then we need to know what will be the value key in the collection struct
* @overwrite If using struct, then do you overwrite elements if the same key id is found. Defaults is true.
*/
function collectAsStruct(
function collectAsMap(
required keyID,
required valueID,
boolean overwrite = true
Expand Down Expand Up @@ -981,6 +1000,30 @@ component accessors="true" {
);
}

/**
* Collect the items to a CFML struct. Please be sure to map the appropriate key and value identifiers
*
* NOTE: the struct type will only work if the collection we are collecting is a struct or an object
* This is a terminal operation.
*
* @keyID If using struct, then we need to know what will be the key value in the collection struct
* @valueID If using struct, then we need to know what will be the value key in the collection struct
* @overwrite If using struct, then do you overwrite elements if the same key id is found. Defaults is true.
*/
function collectAsStruct(
required keyID,
required valueID,
boolean overwrite = true
){
var newStruct = {};
structAppend(
newStruct,
collectAsMap( argumentCollection = arguments ),
true
);
return newStruct;
}

/**
* Returns a Collector which partitions the input elements according to a Predicate, and organizes them into a Map<boolean, List < T>>.
*
Expand Down
9 changes: 6 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,8 @@ Terminal operations are a way to finalize the execution of the stream. Please n
- `iterator()` - Return a java iterator of the stream
- `spliterator()` - Return a java spliterator of the stream
- `close()` - Close the stream
- `toArray()` - Convert the stream back into an array
- `toArray()` - Convert the stream back into a native Java array
- `toNativeArray()` - Convert the stream back into a native Java array. Currently and alias of `toArray` with the hope that in the future `toArray` will return a CFML array.
- `count()` - Count the elements in the stream
- `findAny()` - Find any element in the stream
- `findFirst()` - Find the first element in the stream
Expand All @@ -249,14 +250,16 @@ Terminal operations are a way to finalize the execution of the stream. Please n

Collectors are the way to get out of the streams world and obtain a concrete collection of values, like a list, struct, etc. Here are our collector methods available to you:

- `collect()` - Return an array of the final elements.
- `collect()` - Return an ArrayList of the final elements.
- `collectAsArray()` - Return a CFML Array of the final elements.
- `collectGroupingBy( classifier )` - Build a final collection according to the classifier lambda/closure that will classify the keys in the group. This is usually a structure of elements.
- `collectAverage( mapper, primitive=long )` - Collect an average according to the mapper function/closure.
- `collectSum( mapper, primitive=long )` - Collect a sum according to the mapper function/closure.
- `collectSummary( mapper, primitive=long )` - Collect a statistics struct according to the mapper function/closure .
- `collectAsList( delimiter=",", prefix, suffix )` - Collect results into a string list with a delimiter and attached prefix and/or suffix.
- `collectAsSet()` - Collect the items to a set which doesn't include duplicate elements.
- `collectAsStruct( keyID, valueID, overwrite=true )` - Collect the elements into a struct by leveraging the key identifier and the value identifier from the stream of elements to pass into the collection.
- `collectAsMap( keyID, valueID, overwrite=true )` - Collect the elements into a HashMap by leveraging the key identifier and the value identifier from the stream of elements to pass into the collection.
- `collectAsStruct( keyID, valueID, overwrite=true )` - Collect the elements into a CFML struct by leveraging the key identifier and the value identifier from the stream of elements to pass into the collection.
- `collectPartitioningBy( predicate )` - partitions the input elements according to a Predicate closure/lambda, and organizes them into a Struct of <Boolean, array >.


Expand Down
30 changes: 29 additions & 1 deletion test-harness/tests/specs/MainTests.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,27 @@
} );

given( "The default array collector", function(){
then( "it will produce an array collection", function(){
then( "it will produce an array", function(){
var results = new cbStreams.models.Stream( [ "aa", "aa", "bb", "c", "d", "c" ] ).collect();
expect( results ).toBeInstanceOf( "java.util.ArrayList" );
expect( results.size() ).toBe( 6 );
} );
} );

given( "The CFML array collector", function(){
then( "it will produce a CFML array", function(){
var results = new cbStreams.models.Stream( [ "aa", "aa", "bb", "c", "d", "c" ] ).collectAsArray();
if ( server.keyExists( "lucee" ) ) {
expect( results ).toBeInstanceOf( "lucee.runtime.type.ArrayImpl" );
} else {
expect( results ).toBeInstanceOf( "coldfusion.runtime.Array" );
}
expect( results.len() ).toBe( 6 );
} );
} );

given( "The set collector", function(){
then( "it will produce an set collection", function(){
var setOfNames = new cbStreams.models.Stream( [ "aa", "aa", "bb", "c", "d", "c" ] ).collectAsSet();
expect( setOfNames.size() ).toBe( 4 );
} );
Expand Down Expand Up @@ -460,9 +480,17 @@
} );


given( "The map collector and a key and id mapper", function(){
then( "it will produce a struct of the collection of those mappers", function(){
var results = new cbStreams.models.Stream( people ).collectAsMap( "id", "name" );
expect( results ).toBeInstanceOf( "java.util.HashMap" );
} );
} );

given( "The struct collector and a key and id mapper", function(){
then( "it will produce a struct of the collection of those mappers", function(){
var results = new cbStreams.models.Stream( people ).collectAsStruct( "id", "name" );
expect( results ).notToBeInstanceOf( "java.util.HashMap" );
expect( results ).toBeStruct();
} );
} );
Expand Down
Loading