Kotlin Walk a File Tree

The java.nio.file.Files class has a walk method that returns a Stream used to walk a file tree. The example program lists out the 5 largest files given a starting path and demonstrates how to easily walk through a file system in Kotlin.

package ch9.files

import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.util.stream.Collectors.toList

private fun Path.size() : Long {
    return try {
        Files.size(this)
    } catch (e : Exception){
        -1
    }
}

fun main(args: Array<String>){
    if(args.isNotEmpty()){
        val path = Paths.get(args[0])

        //Open a Stream object
        Files.walk(path)
                //Sort by size
                .sorted { lhs : Path?, rhs : Path? -> compareValues(lhs?.size() ?: -1, rhs?.size() ?: -1)}
                //Collect the result into a list
                .collect(toList())
                //Now reverse the list so that the largest file is first
                .reversed()
                .stream()
                //Open another stream and collect up to 5 files
                .limit(5)
                //Now print the results
                .forEach({it -> println("${it.fileName} \t ${it.size()}") })
    } else {
        println("Usage: start path")
    }
}

Detailed Explanation

The program parses the command line arguments and returns a Path object (line 18). The Path object is passed to the Files.walk() method on line 21. The walk() method returns a Stream object that opens up all of the operations found on a Java 8 Stream. In our case, we wish to sort all files by their size (using the Path.size() extension function found on lines 8-14) on line 23. The result is collected into a list on line 25.

By default, our files are sorted smallest to largest. We can either rework the comparator used on line 23 to reverse sort or just call the reversed() method on the list object. The former idea is most likely more performant but later is very readable. Finally, since we are interested in the five largest files, we open another Stream on the list and limit it to 5 elements. The final operation is to call forEach on the list and print the file name and its size.

References

https://docs.oracle.com/javase/8/docs/api/?java/io/File.html

Advertisement

Kotlin Koans—Part 23

This portion of the Kotlin Koans tutorial appeared to be a review of the concepts I had been working on throughout the collection section. I had to solve three different problems using the collections API. While doing this, I got to revist the Elivis operator (?:), map, maxBy, sumBy, filter, count, and toSet.

Get Customers Who Ordered Product

This problem focused on filtering.

fun Shop.getCustomersWhoOrderedProduct(product: Product): Set {
    // Return the set of customers who ordered the specified product
    return customers.filter { it.orderedProducts.contains(product) }.toSet()
}

The filter method takes a predicate that returns true or false. In this case, I just used the contains method on orderedProducts. If the product is found in orderedProducts, we get a true, otherwise false. Then there is a toSet() operation to transform the collection to a set.

Get Most Expensive Delived Products

This problem was a little more challenging. I had to go back and review how to use the Elivis operator (TODO: Link).

fun Customer.getMostExpensiveDeliveredProduct(): Product? {
    // Return the most expensive product among all delivered products
    // (use the Order.isDelivered flag)
    return orders.filter { it.isDelivered }.map { it.products.maxBy { it.price } }.maxBy { it?.price ?: 0.0}
}

I started with a filter operation to check if an order was delivered or not since the problem statement required me to find the most expensive delivered product. Then I had to use a map operation which allowed me to traverse all delivered orders. At this point, I could use a maxBy operation and check it.price. This builds up a collection of products that contains the most expensive product on each order.

The next part of the operation is to find the most expensive product of all orders. At this point, I have a collection of products so I just needed another maxBy operation. However it was a little more trickey this time. In this case, there was a possibily that the variable it could be null. It’s nice that Kotlin has compiler checks for this sort of thing because I truthfully didn’t realize that I could be working with null objects here. Thus, I had to use the Elvis operator in this final lambda operation.

Get Number Of Times Product Was Ordered

I had to solve this problem by chaining transformations together again.

fun Shop.getNumberOfTimesProductWasOrdered(product: Product): Int {
    // Return the number of times the given product was ordered.
    // Note: a customer may order the same product for several times.
    return customers.sumBy { it.orders.sumBy { it.products.count { it == product } } }
}

A customer has a one to many relationship with orders, and orders have a one to many relationship with products. I needed two sumBy operations to solve this problem. I began with a sumBy on customers. Inside of the lambda, I did another sumBy operation on orders. Once I was traversing orders, I could do a count operation on products and get a total of how many products matched my predicate.

The it.products.count returns a number that gets fed into it.orders.sumBy. The it.orders.sumBy returns a number that gets fed into customers.sumBy. Once customers.sumBy returns, we have a count of the total number of times the specified product was ordered.

You can click here to see Part 22

Kotlin Koans—Part 22

More functional programming on the horizon. This portion of Kotlin Koans demonstrated folding. I personally had never tackled a challenge like this so it took me more time to figure it out than the other problems. My job was to go through all customers and the products they ordered and reduce them down to a single set of objects. Here is the Kotlin code.

fun Shop.getSetOfProductsOrderedByEveryCustomer(): Set {
    // Return the set of products ordered by every customer
    return customers.fold(allOrderedProducts, {
        orderedByAll, customer ->
            orderedByAll.intersect(customer.orderedProducts)
    })
}

As usual, I tried to do the same problem in Java for comparison purposes, but I wasn’t able to figure it out! (If you know the solution, please leave it in the comments section!). I’ll have to admit that I am weak in some of the functional programming areas.

You can click here to see Part 21.

Kotlin Spring Security Tutorial

Just about anybody can appreciate the value of securing a web application. After all, who would do their online banking on an unsecured website? Of course, it’s not just online banking that requires security. Just about any website that has information that requires protecting needs security.

Spring provides web security modules that help us secure our applications. As with everything in Spring, it’s really easy to use an configure.

Define a Security Class

Spring has us extend the WebSecurityConfigurerAdapter class and annotate it with @Configuration and @EnableWebSecurity. Here is an example Kotlin class that enables our web security and forces all requests to the web application to be authenticated.

@Configuration //Make this as a configuration class
@EnableWebSecurity //Turn on Web Security
class SecurityWebInitializer : WebSecurityConfigurerAdapter(){
    override fun configure(http: HttpSecurity) {
        //This tells Spring Security to authorize all requests
        //We use formLogin and httpBasic
        http
                .authorizeRequests()
                    .anyRequest()
                    .authenticated()
                .and()
                    .formLogin()
                .and()
                    .httpBasic()
    }

    override fun configure(auth: AuthenticationManagerBuilder) {
        //This code sets up a user store in memory. This is
        //useful for debugging and development
        auth
                .inMemoryAuthentication()
                    .withUser("bob")
                    .password("belcher")
                    .roles("USER")
                .and()
                    .withUser("admin")
                    .password("admin")
                    .roles("USER", "ADMIN")
    }
}

The first method, configure(http: HttpSecurity) calls methods on the http object. This class has a chaining interface and by calling the proper methods, we can tailor the security configuration to suit our needs. The methods are plain english, so the code ends up being highly self-documenting.

The other configure method accepts an auth: AuthenticationManagerBuild. The auth object is used to configure a data store for users. For the purposes of this post, we are creating an inMemoryAuthentication. This is useful for development and debugging purposes.

The Controller Class

There isn’t anything special about the controller class. That’s a feature of Spring Security. Security is a cross cutting concern which means that the main application code should not have to concern itself with security. Instead, Spring uses Aspect Orientated programming to secure our application.

Sometimes it’s useful to know what user is logged into this system. There is a an example of how to access this information and pass it back to the view. (Readers who are not familiar with Spring MVC can refer here for an example of Spring MVC).

@Controller
@RequestMapping("/")
class IndexController {

    @RequestMapping(method = arrayOf(RequestMethod.GET))
    fun doGet(model : Model) : String {
        //We can access the current user like this
        val authorization = SecurityContextHolder.getContext().authentication

        //Send the user name back to the view
        model.addAttribute("username", authorization.name)
        return "index"
    }
}

The SecurityContextHolder class provides an access point to the current logged in user. Spring calls it an authentication. The object returns contains information about the user such as the user name.

Conclusion

Here is a video of logging into this site in action.

You can get the code from my github page here.

Kotlin Koans—Part 21

The Kotlin Koans tutorial continues with more demonstrations about the extensions on collection classes. This portion of the tutorial was a partitioning problem where I had to return the customers that have not had their orders delivered. Here is the code.

fun Shop.getCustomersWithMoreUndeliveredOrdersThanDelivered(): Set {
    // Return customers who have more undelivered orders than delivered
    return customers.partition { it.orders.all { it.isDelivered } }.second.toSet()
}

Kotlin adds a partition method to it’s collection classes. The partition method takes a lambda expression that returns a boolean. Inside of this lambda, I used the all (#TODO Link to All) method on the orders collection. Once again, I am returning a boolean value.

Now for the coolest part. Kotlin has a pair class that has a first and second method. Since I need the orders that are not delievered, I use the second property on the Pair class. At this point, second is holding a collection of Customers whose orders are not delivered. Finally, I can use the toSet (#TODO Link) method to transform the collection into a set.

Like the last few portions of this tutorial, I decided to compare the Kotlin code to the Java 8 code. Here is what I came up with.

public static Set getCustomersWithMoreUndeliveredOrdersThanDelivered(Shop shop){
    return new HashSet(shop.getCustomers()
            .stream()
            .collect(Collectors.partitioningBy((Customer c) -> c.getOrders().stream().allMatch(Order::isDelivered)))
            .get(false));
}

You can click here to see Part 20.

Kotlin Koans—Part 20

Grouping objects by a property and storing them into a map is a challenge that all developers have faced at some point in time. For example, you may have a collection of Customers and you wish to find out which Customers live in each city. Basically, you want a map where City is the key and a Collection of Customers associated with that City is the value.

This was exactly the problem that Kotlin Koans tutorial had me do.

fun Shop.groupCustomersByCity(): Map {
    // Return a map of the customers living in each city
    return customers.groupBy { it.city }
}

I was able to arrange all of the Customers by city with just one line of Kotlin code. The related Java code wasn’t that difficult either, but I did have to search for the solution since it wasn’t quite as clear as the Kotlin approach.

public static Map groupCustomersByCity(Shop shop){
    return shop.getCustomers().stream().collect(Collectors.groupingBy(Customer::getCity));
}

What helped me with the Kotlin approach was that since the groupBy method was direclty on the Collection object, my IDE was able to supply me with the groupBy method. That’s not the case with the Java approach since it’s using a static method on the Collectors class. It also didn’t occur to me to use the collect method on the Stream object either. I was looking for something that said group in it.

You can click here to see Part 19.

Kotlin Koans—Part 19

This section of the Kotlin Koans tutorial continued onward with Kotlin’s collection API enhancement. The challenge in this section use to total the price of all products a customer purchased. Here is the code

fun Customer.getTotalOrderPrice(): Double {
    // Return the sum of prices of all products that a customer has ordered.
    // Note: a customer may order the same product for several times.
    return orders.sumByDouble { it.products.sumByDouble { it.price } }
}

The collection API in Kotlin has a sumByDouble method, which takes a lambda expression. The lambda let’s developers chain function calls. In this case, each Customer had a collection of Products in each Order. To get the price of all Products ordered, I needed the sum of the price of all products in a order. This was easy enough to do because I just made a nested call to sumByDouble on it.products and then told it to sum on it.price.

Here is Java code that solves the same problem.

public static double getTotalOrderPrice(Customer customer){
    return customer
            .getOrders()
            .stream()
            .mapToDouble(
                    order -> order.getProducts()
                                    .stream()
                                    .mapToDouble(Product::getPrice)
                            .sum())
            .sum();
}

You can click here to see Part 18

Kotlin Koans—Part 18

This portion of the Kotlin Koans tutorial deals with sorting a collection functionally. As usual with Kotlin, this wasn’t a very difficult problem. As a matter of fact, it’s only one line of code.

fun Shop.getCustomersSortedByNumberOfOrders(): List {
    return customers.sortedBy { it.orders.size }
}

We basically just call the sortedBy method and place the property we want to sort by inside of the curly braces { }. In this case, I wanted to sort by the number of orders my hypothetical customer placed, so I used it.orders.size.

Just for kicks, I decided to try this in Java 8 to see the difference.

public static List getCustomersSortedByNumberOfOrders(Shop shop){
    return shop.getCustomers()
            .stream()
            .sorted(Comparator.comparingInt(customer -> customer.getOrders().size()))
            .collect(Collectors.toList());
}

Once again, we can do the same thing in Java that we can do in Kotlin at the expense of more verbosity. Also, I think in this case, the Java approach is more difficult to learn and more prone to errors since we are chaining a bunch of functions together to achieve the same result that we can do in one line of Kotlin code.

You can click here to see Part 17

Kotlin Koans—Part 17

This part of Kotlin Koans continues to build on the features Kotlin offers on collection. Most of these methods will look familiar to people who have worked with Java 8 streams.

In this portion of the tutorial, I had to work with the maxBy method. It’s a nice little shortcut method to find an item based on a property. There is also a companion minBy.

fun Shop.getCustomerWithMaximumNumberOfOrders(): Customer? {
    // Return a customer whose order count is the highest among all customers
    return customers.maxBy { it.orders.size }
}

fun Customer.getMostExpensiveOrderedProduct(): Product? {
    // Return the most expensive product which has been ordered
    return orderedProducts.maxBy { it.price }
}

I was curious about what it would take to solve this problem in Java. Here is what I came up with.

public static Optional getCustomerWithMaximumNumberOfOrders(Shop shop){
    return shop.getCustomers().stream().max(Comparator.comparingInt(lhs -> lhs.getOrders().size()));
}

I can’t say it was too brutal, but I think maxBy is much easier to read and understand as opposed to stream().max(Comparator.comparingInt(lhs -> lhs.getOrders().size()))

You can click here to see Part 16

Kotlin Koans—Part 16

This portion of the Kotlin Koans tutorial continued with collection operations. Again, many of these operations are available in JDK8, but are missing in Android Java and previous versions of JDK. I got a few different demonstrations about what you can do with Kotlin here.

Operator Overloading

Kotlin supports operator overloading. I think this was a good move. C++ has operator overloading, but it was left out in Java. At the time, some people brought up that operator overloading was a source of bugs and it impacted code readability. I used to be one of those people, but frankly, I have been swayed back towards operator overloading. Operator overloading cuts down on verbosity in your code, and I can’t truthfully say I have seen additional bugs do to operator overloading.

Here is the first portion of Kotlin code

fun Customer.isFrom(city: City): Boolean {
    // Return true if the customer is from the given city
    return this.city == city
}

All

Kotlin collections have an all { } method that accepts a predicate. You can use it check if all items in a collection match the criteria specified in the predicate.

fun Shop.checkAllCustomersAreFrom(city: City): Boolean {
    // Return true if all customers are from the given city
    return customers.all { it.city == city }
}

Any

The any { } method is similar to all, but only one item in the collection has to match the predicate for it to return true.

 fun Shop.hasCustomerFrom(city: City): Boolean {
    // Return true if there is at least one customer from the given city
    return customers.any{ it.city == city }
}

Count

Kotlin collections have a count method also that returns the number of items that match the criteria provided in the predicate.

fun Shop.countCustomersFrom(city: City): Int {
    // Return the number of customers from the given city
    return customers.count { it.city == city }
}

Find Any

We also have a find any method which returns an item that matches the criteria in the predicate.

fun Shop.findAnyCustomerFrom(city: City): Customer? {
    // Return a customer who lives in the given city, or null if there is none
    return customers.find { it.city == city }
}

it

You may have noticed it popping up in all of these lambda expressions. As long as a SAM interface has only one parameter, developers can use a special it variable to refer to that parameter.

You can click here to see Part 15

%d bloggers like this: