Get list of properties from collection Into unified list using Guava - java-7

My company requires that we use Guava's functions & predicates whenever we loop through a collection of objects. While I don't necessarily agree that it should be this way, it's my companies standard so please don't give me comments about how it's not efficient or things like that :)
I need, using Guava in Java 1.7 specifically, to find a way to take a collection of objects, and get all of the inner fields into a unified list. This is as far as I've gotten but I have not been able to get inner fields:
public static final Function<Group, String> GROUP_TO_GROUP_NAME =
new Function<Group, String>()
{
#Override
public String apply(Group group)
{
return group.getGroupName();
}
};
public static List<String> transformToGroupNames(List<GroupCollection> groupCollections)
{
List<Group> groups = new ArrayList<>();
for (GroupCollection groupCollection: groupCollections)
{
groups.addAll(groupCollection.getGroups());
}
return FluentIterable.from(groups)
.transform(GROUP_TO_GROUP_NAME)
.filter(Predicates.notNull())
.toList();
}
My goal is to replace the loop through the groupCollections

To flatten the group collections to a single group collection you can use FluentIterable.transformAndConcat(Function):
public static final Function<GroupCollection, List<Group>> GROUP_COLLECTIONS_TO_GROUP_COLLECTION =
new Function<GroupCollection, List<Group>>() {
#Override
public List<Group> apply(GroupCollection input) {
return input.getGroups();
}
};
public static final Function<Group, String> GROUP_TO_GROUP_NAME =
new Function<Group, String>() {
#Override
public String apply(Group group) {
return group.getGroupName();
}
};
public static List<String> transformToGroupNames(List<GroupCollection> groupCollections) {
return FluentIterable.from(groupCollections)
.transformAndConcat(GROUP_COLLECTIONS_TO_GROUP_COLLECTION)
.transform(GROUP_TO_GROUP_NAME)
.filter(Predicates.notNull())
.toList();
}

Related

How to create a api which return array of string?

["Non Dox", "Dox"] --> create a method for this and how i call in controller method also
i want this from api how i will be able to do it in spring boot
public static String[] demo()
{
String[] xs = new String[] {"Dox","NonDox"};
return xs;
} //method for array of string
#GetMapping("/url") public String[] getArray(){ return employeeService.demo(); } //call in controller
I'm not sure if you want to stick with String[] arrays, but you can create a List<String> instead and have a Controller return this. I've set up such a Controller for you (I was doing some research on Spring Boot and primitives/arrays but I couldn't find any documentation on best practices for this).
Your static List would look like this:
static List<String> list() {
return new ArrayList<>() {
{
add("Dox");
add("NonDox");
}};
}
#GetMapping("/url")
public List<String> getList(){
return list();
}

Automapper to Map two List Classes of different structure and also Memberwise explicit Mapping

I have 4 classes namely ClassA, ClassADto, ClassAA(inner class to ClassA) and the final Result class.
ClassAA
{
public int HouseNumber{get;set;}
public string StreetName{get;set;}
public string State{get;set;}
}
ClassA
{
public int Age{get;set;}
public string Name{get;set;}
public ClassAA AObj[get;set;}
}
ClassADto
{
public int Age{get;set;}
public string Name{get;set;}
}
class Result
{
public string StreetName{get;set;}
public int TotalCount{get;set;}
public int TodaysDate{get;set;}
public List<ClassADto> AObjectsList{get;set;}
}
Now my aim is map the 'Result' class with the List of ClassA object to fill it the property 'AObjectsList' as below:
Result data= map mapper.map>(obj);
Also at the same time in automapper i want to use custom function either using 'Resolve' or 'AfterMap' to set properties like 'TodaysDate' to current datetime of system and property 'TotalCount' by counting the number of data.
I tried in many ways using 'CreateMap' and also used 'ForMembers' as from 'classAA' we only need the 'StreetName' but it didn't work. Need some help please.
One time typing approach ;)
public static Result ToResult(this List<ClassA> users)
{
return new Result
{
TotalCount = users.Count,
TodaysDate = DateTime.Today,
AObjectsList = users
.Select(user => new ClassADto
{
Name = user.Name,
Age = user.Age
})
.ToList()
};
}
// Usage
var users = new List<ClassA> { new ClassA(), new ClassA() };
var result = users.ToResult();

Java stream : convert list of one object to other

I am trying to learn map function in Stream
public class EmployeeInformationTest {
public static void main(String args[]) {
List<Employee> employees = Arrays.asList(
new Employee("Jai"),
new Employee("Adithya"),
new Employee("Raja"));
List<String> names = employees.stream()
.map(s -> s.getEmployeeName()) // Lambda Expression
.collect(Collectors.toList());
System.out.println(names);
}
}
we have above code and somehow it is giving us List of String from List of Employee. Say, we have other class Person in which we have field as name
public class Person {
private String name;
}
so is it feasible via map or some other function in stream so that I can get the List of Person rather than List of String in above code
sure thing, just change the map function to:
.map(s -> new Person(s.getEmployeeName()))
or if there is no such constructor:
.map(s -> {
Person p = new Person();
p.setName(s.getEmployeeName());
return p;
})

Passing array of reg expressions to spring based mongo #Query

I'm using Spring boot with mongodb. I've extended PagingAndSortingRepository repository and added the following function
#Query("{'title':{ $nin: [?0]}}")
List<Item> findItem(String[] exclude);
I want to be able to pass it an array of regular expressions such as /dog/,/cat/,/horse/ to exclude any item that may have one of these in it's title.
The above function does not work because the exclude is converted to a string. How can I pass an array of regular expressions to be able to do the above?
You can work it out by using a Querydsl predicate in one of your controller method.
Add something like this to your controller:
#RequestMapping(value="/search/findByNameRegexNotIn", method = RequestMethod.GET)
#ResponseBody
public List<Item> findByNameRegexNotIn(#RequestParam(name = "name") List<String> names) {
// build a query predicate
BooleanBuilder predicate = new BooleanBuilder(); // comes from the Querydsl library
for (String name : names) {
predicate.and(QItem.item.name.contains(name).not()); // the QItem class is generated by Querydsl
}
List<Item> items = (List<Item>)repository.findAll(predicate);
return items;
}
You can of course add a Pageable parameter and return a Page<Item> instead of a List.
Edit: another solution if you use Querydsl for this sole purpose is to override the default bindings of your query parameter.
public interface ItemRepository extends CrudRepository<Item, String>,
QueryDslPredicateExecutor<Item>, QuerydslBinderCustomizer<QItem> {
#Override
default public void customize(QuerydslBindings bindings, QItem item) {
bindings.bind(item.name).all(
(path, values) -> path.matches(StringUtils.collectionToDelimitedString(values, "|")).not());
// disable query on all parameters but the item name
bindings.including(item.name);
bindings.excludeUnlistedProperties(true);
}
}
The controller method:
#RequestMapping(value="/search/query", method = RequestMethod.GET)
#ResponseBody
public List<Item> queryItems(
#QuerydslPredicate(root = Item.class) Predicate predicate) {
List<Item> items = (List<Item>)repository.findAll(predicate);
return items;
}
Edit: if you don't wan't to override the default QuerydslBinderCustomizer#customize, you can also implement your own binder and specify it in the controller method.
public interface ItemRepository extends CrudRepository<Item, String>,
QueryDslPredicateExecutor<Item> {
...
}
The controller method:
#RequestMapping(value="/search/query", method = RequestMethod.GET)
#ResponseBody
public List<Item> queryItems(
#QuerydslPredicate(root = Item.class, bindings = ItemBinder.class) Predicate predicate) {
List<Item> items = (List<Item>)repository.findAll(predicate);
return items;
}
The binder class:
class ItemBinder implements QuerydslBinderCustomizer<QItem> {
#Override
public void customize(QuerydslBindings bindings, QItem item) {
bindings.bind(item.name).all(
(path, values) -> path.matches(StringUtils.collectionToDelimitedString(values, "|")).not()
);
bindings.including(item.name);
bindings.excludeUnlistedProperties(true);
}
}
Edit: for the sake of exhaustivity and those who don't want to hear about Querysl. Using the solution proposed in Spring Data Mongodb Reference.
Define a custom repository interface:
interface ItemRepositoryCustom {
public Page<Item> findByNameRegexIn(Collection<String> names, Pageable page);
}
Define an custom repository implementation (Impl postfix required!):
public class ItemRepositoryImpl implements ItemRepositoryCustom {
#Autowired
private MongoOperations operations;
#Override
public Page<Item> findByNameRegexNotIn(Collection<String> names, Pageable pageable) {
String pattern = StringUtils.collectionToDelimitedString(names, "|");
// this time we use org.springframework.data.mongodb.core.query.Query instead of Querydsl predicates
Query query = Query.query(where("name").regex(pattern).not()).with(pageable);
List<Item> items = operations.find(query, Item.class);
Page<Item> page = new PageImpl<>(items, pageable, items.size());
return page;
}
}
Now simply extend ItemRepositoryCustom:
public interface ItemRepository extends MongoRepository<Item, String>, ItemRepositoryCustom {
...
}
And you're done!
You can pass a java.util.regex.Pattern[] to the method. This will be converted to regex array under the hood:
#Query("{'title':{ $nin: ?0}}")
List<Item> findItem(Pattern[] exclude);

How to test these kinds of methods (from Service layer)

I'm fiddling around with Mockito and Spring MVC. I'm trying to write unit tests for the code I've just written.
This is my CategoryService class:
#Service
public class CategoryService {
#Autowired
#Qualifier("categoryDaoImpl")
private CategoryDao categoryDao;
public void addCategory(Category category) {
category.setId(getLastCategoryId() + 1);
categoryDao.addCategory(category);
}
public Category getCategoryById(int id) {
return categoryDao.getCategoryById(id);
}
public List<Category> getCategories() {
return categoryDao.getAllCategories();
}
public int getCategoriesCount() {
return categoryDao.getCategoriesCount();
}
public int getLastCategoryId() {
if (categoryDao.getAllCategories().size() == 0) {
return 0;
}
return Collections.max(categoryDao.getAllCategories()).getId();
}
public CategoryDao getCategoryDao() {
return categoryDao;
}
public void setCategoryDao(CategoryDao categoryDao) {
this.categoryDao = categoryDao;
}
I've already tested CategoryDao with nearly 100% coverage.
And now I want to test CategoryService, but I have no idea how to test it, I mean methods like: addCategory, getCategoryById, getAllCategories, getCategoiesCount etc.
They're just talking to the DAO pattern, but what if another person changes its logic? I'd be glad if you told me or showed how to write a tests for such short methods.
As far as CategoryService is concerned, I only wrote tests for getLastCategoryId():
#Test
public void shouldGetLastCategoryIdWhenListIsEmpty() {
//given
List<Category> list = new ArrayList<Category>();
Mockito.when(categoryDao.getAllCategories()).thenReturn(list);
//when
int lastCategoryId = categoryService.getLastCategoryId();
//then
assertThat(lastCategoryId, is(0));
}
#Test
public void shouldGetLastCategoryIdWhenListIsNotEmpty() {
//given
List<Category> list = new ArrayList<Category>();
list.add(new Category(1, "a", "a"));
list.add(new Category(3, "a", "a"));
list.add(new Category(6, "a", "a"));
Mockito.when(categoryDao.getAllCategories()).thenReturn(list);
//when
int lastCategoryId = categoryService.getLastCategoryId();
//then
assertThat(lastCategoryId, is(6));
}
Thank you very much for help :)
Best regards,
Tom
You need to verify that the service methods behave as per their contracts even if they are modified in the future.
For e.g. The addCategory(Category c) method adds the category. This can be verified by verifying the categoryDao.addCategory() method is called with the category object that has the required properties set. In this case the id should be set to the lastCategoryId. Verifying could simply be done by create a spy of CategoryDao class (would be simpler then using third party libraries like mockito.
The test cases for getCategoryById(), getCategories() and getCategoriesCount() method could verify that the values returned are the ones returned by the dao.
I understand that this would mean just one test case per method, but these test cases just confirm that if there is more logic added in the service method implementation, the contract remains intact.
Here's one test case for addCategory()
public class CategoryServiceTest {
private CategoryService service;
private CategoryDaoSpy daoSpy;
#Before
public void setUp() {
service = new CategoryService();
daoSpy = new CategoryDaoSpy();
service.setCategoryDao(daoSpy);
}
#Test
public void shouldSaveCategoryWhenCategoryPassed() {
Category category = new Category();
service.addCategory(category);
assertEquals(daoSpy.getAddCategoryCallCount(), 1);
assertEquals(daoSpy.getCategories().size(), 1);
assertEquals(daoSpy.getCategories().get(0).getId(), 1);
}
}
public class CategoryDaoSpy extends CategoryDao {
private int addCategoryCallCount = 0;
private List<Category> categories = new ArrayList<>();
#Override
public void addCategory(Category category) {
this.addCategoryCallCount++;
categories.add(category);
}
public int getAddCategoryCallCount() {
return addCategoryCallCount;
}
public List<Category> getCategories() {
return categories;
}
#Override
public List<Category> getAllCategories() {
return Collections.emptyList();
}
}

Resources