EnumSet Efficiency

EnumSet Efficiency 


EnumSet is Specialized Set which only takes Enum elements. Look at the signature of this class.

public abstract class EnumSet<E extends Enum<E>>
extends AbstractSet<E>
implements Cloneable, Serializable


The Beauty of EnumSet is we can perform any collection operations like (add,remove etc. ) on Enum as Enumset is a collection furthermore it provides some Static methods by which we can do union,range check,none etc. operation.

So by using Enumset we can dynamically add Enum element remove an element or perform union operation . we can use it in an efficient way and use its power but still Developer are not used this they put Enum in a Set or any other collection if required.


So where we can Use EnumSet?

Ummm a probable use case comes in my mind is ,
Role and operation implementation not only that say from UI we can manipulate it and can create a new Role with new operation Set.

To be specific say I have Three types of role say Self,Friend, and Guest.
As you can guess Owner of the profile got Self role , Friends of owner got friend role and any unknown person got Guest role. Now Owner wants to create a new role for few guests , those can perform Friend operation as well as guest operations both.


How we will implement that,

Obvious one can think of Bit representation for operations and do an anding operation to check is particular operation is valid for a role or not, the same way he can create a new role I don’t go for that implementation that will hard to maintain. rather I will try to solve it through EnumSet.

Code:

  1. I create an Operation Enum where I store all the possible Operations

    package com.example.enumtest;

    public enum Operation {
       
       VIEW_PROFILE,EDIT_PROFILE,DELETE_PROFILE,VIEW_ALBUM,EDIT_ALBUM,DELETE_ALBUM,COMMENT,RATE_PROFILE

    }

    2. Then I create a Role Enum and associate permitted operations with those roles.

    package com.example.enumtest;

    import java.util.EnumSet;

    import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils.Collections;

    public enum Role {
       
       SELF(EnumSet.of(Operation.VIEW_PROFILE,Operation.VIEW_ALBUM,Operation.EDIT_PROFILE,Operation.EDIT_ALBUM,Operation.DELETE_PROFILE,
              Operation.DELETE_ALBUM,Operation.COMMENT)),
             
       FRIEND(EnumSet.of(Operation.VIEW_ALBUM,Operation.VIEW_PROFILE,Operation.COMMENT)),
       
       GUEST(EnumSet.of(Operation.VIEW_PROFILE,Operation.RATE_PROFILE));
       
       
       EnumSet<Operation> operationSet;
       Role(EnumSet<Operation> operationSet){
          this.operationSet=operationSet;
       }
       

    }

    Look in Role Constructor I pass EnumSet<Operation>, and when we define the Enum element I called  a Static method of  on EnumSet. Which will perform a union operation.


    3. Now each role has its set of operations and we can easily print them by traversing on operationSet ,easily check an operation is permitted or not by using

    operationSet.contains(operation)


    4. Now I want to add a new Role which can perform both Friend and guest operations.

    package com.example.enumtest;

    import java.util.EnumSet;

    public class ProfileManager {
       
       
       public static void printOperationForCustomRole(EnumSet<Role>roles)
       {
          EnumSet<Operation> mergeSet = EnumSet.noneOf(Operation.class);
          for(Role role: roles)
          {
              for(Operation op : role.operationSet)
              mergeSet.add(op);
          }
         
          System.out.println(mergeSet);
       }
       
       public static void main(String[] args) {
         
          ProfileManager.printOperationForCustomRole(EnumSet.of(Role.FRIEND,Role.GUEST));
         
       }

    }


    Look , how easily we can do it just pass Role.Friend and Role.Guest in printOperationForCustomRole() role method and create a new Operation set which holds all the operations of friend and Guest.


    Output:

    [VIEW_PROFILE, VIEW_ALBUM, COMMENT, RATE_PROFILE]






Java : Extensible Enum with Interface

 Extensible Enum with Interface

 

Overview

In Java Enum is a powerful data type. Many places user uses Enum To get advantages from Enum type. Like In a Static Factory method it wise decision to pass Enum type rather than pass String. Below , I mention some situations where using Enum is advantageous.

Enum Advantages

    1. In a Static Factory method passing Enum type as argument make the method typesafe. Method users can’t pass an arbitrary value to this method.
    2. Instead of using bit fields using Enum and EnumSet make the code cleaner and easy to maintain.
    3. Using Enum one can achieve Singleton pattern which is inherently Thread Safe.
    4. Using Strategy Enum Pattern one can get rid of If/Switch statements.
Although, Enum has several advantages but it has one major disadvantage.

Enum DisAdvantage

    1. Unlike Class, we can not extend Enum.
So the Question is

“Can we Extend Enum and When it is needed?”

Yes we can emulate the extensibility in Enum but we have to play in a strategic way ,
We know that Enum can’t be extended but we know the fact that an Interface can be extended and Enum can implement the Interface. So combining these two statements we can achieve extensibility. Where Enum can’t be extended but an interface can so If we use “Coding to an Interface” Strategy we can easily replace BaseType enum with Our Extended Enum.
Now coming to the use case,
According to Joshua Bloch ,“There is at least one compelling use case for extensible enumerated types, which is operation codes, also known as opcodes. An opcode is an enumerated type whose elements represent operations on some machine, such as the Operation”
Sometimes it is desirable to let the users of an API provide their own operations,effectively extending the set of operations provided by the API.”


According to Josh Bloch In a case of operation, we can provide some basic operation in an Enum like a simple calculator and basic operations are plus ,minus etc but if API Users want more like XOR , Square root, they can achieve it through extending Operation Interface and create a new Enum.

Steps For Achieving Extensibility


Let’s take a Use Case , We have an Enum call Direction in an API ,it has entries for NORTH,SOUTH,EAST,WEST but most of the cases API Users use these basic directions but when it is about to showing the shortest path between source and destination API Users need some advanced direction like NORTH-EAST,NORTH-WEST etc.


How judiciously we implement the API so Users can have the option to extend the Basic Direction Enum?


Steps.
    1.Create an Interface called Direction and declares a method called showDirection().
    2. Create a BasicDirection enum by implement Direction interface.
    3. Put entries for NORTH,SOUTH,EAST,WEST.
    4. Please note that as it implements Direction interface , each Enum has to override showDirection method.
    5. Create an AdVANCEDIRECTION enum with NORTH-EAST,NORTH-WEST etc entries.
    6. Use this Enum anywhere.
    Java Code :
    Direction Interface

package com.example.enumtest;

public interface Direction {
   
    public void showDirection();



BasicDirection Enum 

package com.example.enumtest;

public enum BasicDirection implements Direction{
   
    NORTH{

        @Override
        public void showDirection() {
            System.out.println("I am NORTH");
          
        }
      
    },
    SOUTH{

        @Override
        public void showDirection() {
            System.out.println("I am South");
          
        }
      
    },
    EAST{

        @Override
        public void showDirection() {
            System.out.println("I am EAST");
          
        }
      
    },
    WEST{

        @Override
        public void showDirection() {
            System.out.println("I am WEST");
          
        }
      
    }

}


AdvanceDirection Enum

package com.example.enumtest;

public enum AdvanceDirection implements Direction{
    NORTHEAST{

        @Override
        public void showDirection() {
            System.out.println("I am NORTH-EAST");
          
        }
      
    },
    NORTHWEST{

        @Override
        public void showDirection() {
            System.out.println("I am NORTH-WEST");
          
        }
      
    },
    SOUTHEAST{

        @Override
        public void showDirection() {
            System.out.println("I am SOUTH-EAST");
          
        }
      
    },
    SOUTHWEST{

        @Override
        public void showDirection() {
            System.out.println("I am SOUTH-WEST");
          
        }
      
    }


}
 


DirectionDriver Class 

package com.example.enumtest;

public class DirectionDriver {
   
    public static void printDirection(Direction op)
    {
        op.showDirection();
    }
   
    public static <T extends Enum<T> & Direction> void  printDirections(Class<T> clazz)
    {
        for(Direction direction : clazz.getEnumConstants())
        {
            direction.showDirection();
        }
    }
   
    public static void main(String[] args) {
      
        DirectionDriver.printDirection(BasicDirection.EAST);
        DirectionDriver.printDirection(AdvanceDirection.SOUTHWEST);
      
        DirectionDriver.printDirections(BasicDirection.class);
        DirectionDriver.printDirections(AdvanceDirection.class);
      
    }

}

 

Output

I am EAST
I am SOUTH-WEST
I am NORTH
I am South
I am EAST
I am WEST
I am NORTH-EAST
I am NORTH-WEST
I am SOUTH-EAST
I am SOUTH-WEST





Please pay attention to the class DirectionDriver, here I create two methods
    printDirection which takes Direction as Input and I pass an Enum to it.
    Another version is printDirections method it prints all Enum entries to achieve that
I make a generic type which says T must be an Enum and a subtype of Direction by <T extends Enum<T> & Direction> . then pass class instance so I can iterate over EnumConstants.








 




Spring Data (Part 5): Paging and Sorting

Paging and Sorting


Overview

When we perform bulk operations, like finding all "Person"s from the database or finding everyone based on a country, often we do the paging so that we can present a small data chunk to the end user and, in the next request, we fetch the next data chunk. By doing this, we got two main advantages.

Advantages

Enhancing readability for end users if we show whole data on a page then the page will be enough long with Scrollbar, the end user has to scroll for finding a particular person which is a bad UI design.
Reduce the Query time and enhance the performance as in spite of fetch all data we only fetch a small chunk of data so less query time. Many UI technology support client side paging which at a time fetch all data and based on use request show paginated data but this is not reducing the query time it only provide the advantage number 1.

Disadvantages:
To request every data chunk One server trip is required. You can optimize it through caching .
2 . When an end user in the process of fetching data another Person added to the system it may possible, the last entry of a page again shown in next page as a first entry.

But we are always using paging to fetch a small chunk of data rather than whole data.

Spring Data and Pagination

Spring data provides support for pagination , It creates all the logic to implement a paging like a count the rows for total pages , create data store specific queries etc.
To implement Paging is very easy in Spring data just we need to follow the below steps,
1. In your custom repository just extends PagingAndSortingRepository
2. Create a PageRequest Object which is an implementation of Pageable interface
This PageRequest Object takes page number, limit of the page (page size) and sorts direction and sort field.
3. By passing requested page number and page limit you can get the data for this page.
If you pass a wrong page number Spring data will take care of that and not return any data.

Paging Code implementation
1. Create a repository which extends PagingAndSortingRepository

package com.example.repo;
import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
import com.example.person.Person;
@Repository
public interface PersonRepositary extends PagingAndSortingRepository<Person, Long>,QueryDslPredicateExecutor<Person> {
@Query("select p from Person p where p.country like ?1 order by country")
List<Person> findByCountryContains(String country);
List<Person> findPersonByHobbyName(String name);
@Query("select p from Person p where p.id = ?1 and  country='America'")
Person findOne(Long id);
}
 
 
2.Create Domain Objects
 
package com.example.person;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class Person {
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
private String country;
private String gender;
@OneToMany(mappedBy="person",targetEntity=Hobby.class,
       fetch=FetchType.EAGER,cascade=CascadeType.ALL)
List<Hobby> hobby;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<Hobby> getHobby() {
return hobby;
}
public void setHobby(List<Hobby> hobby) {
this.hobby = hobby;
}
public void addHobby(Hobby ihobby)
{
if(hobby == null)
{
hobby = new ArrayList<Hobby>();
}
hobby.add(ihobby);
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", country=" + country + ", gender=" + gender + "]";
}
}



3. Fetch all person, Here I assume per page entry is one so create a PageRequest Object with limit 1 and requesting for the first page.

package com.example.person;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import com.example.repo.HobbyRepository;
import com.example.repo.PersonRepositary;
import com.querydsl.core.types.dsl.BooleanExpression;
@SpringBootApplication
@EnableJpaRepositories("com.example.repo")
public class PersonApplication {
@Autowired
HobbyRepository hRepo;
private static final Logger log = LoggerFactory.getLogger(PersonApplication.class);
@Bean
public CommandLineRunner demo(PersonRepositary repository) {
findAll(repository);
return null;
}
private PageRequest gotoPage(int page)
{
PageRequest request = new PageRequest(page,1)
return request;
}
private void findAll(PersonRepositary repository)
{
Iterable<Person> pList = repository.findAll(gotoPage(0));
for(Person p : pList)
log.info("Person " + p);
}
public static void main(String[] args) {
 SpringApplication.run(PersonApplication.class, args);
}
}
 
 

Output
 
 
Hibernate: 
    select
        count(person0_.id) as col_0_0_ 
    from
        person person0_
Hibernate: 
    select
        person0_.id as id1_1_,
        person0_.country as country2_1_,
        person0_.gender as gender3_1_,
        person0_.name as name4_1_ 
    from
        person person0_ limit ?
Person Person [id=13, name=Samir mitra, country=America, gender=male]
 


Paging and Sorting Code implementation:

To do sorting we have to pass the sort direction and sorting fields along with page number and limit. Suppose we want to sort by country name in ascending order we modify the goto
 method like following.

private PageRequest gotoPage(int page)
{
PageRequest request = new PageRequest(page,1,Sort.Direction.ASC,"country");
return request;
}
 
 
 
Output:
 
 select
        count(person0_.id) as col_0_0_ 
    from
        person person0_
Hibernate: 
    select
        person0_.id as id1_1_,
        person0_.country as country2_1_,
        person0_.gender as gender3_1_,
        person0_.name as name4_1_ 
    from
        person person0_ 
    order by
person0_.country asc limit ?



Here we pass the ascending order and country property.