java get collection of methods - java

I have some helper classes for testing with the following structure:
public class EntitiesForTest {
public static Entity firstEntity() {
return new Entity(/*some dummy data*/)
}
public static Entity secondEntity() {...}
...
public static Entity nthEntity() {...}
public static List<Entity> allEntities() {???}
}
The purpose of this classes is to have some objects to test the upper layers of my system, like having some JSON data to test a REST service. This technique is not mine but from an online course I'm taking and is pretty cool.
I'd like to know if there is a way to construct a List<Entity> based on the static inherited methods of the class and with the Collection framework. I can do Arrays.asList(/*call the methods one by one comma-separated*/) but there must be a smarter, functional and reusable way of doing this.
Thanks in advance for your answers.

"Modern" Way
public static List<Entity> getEntities() {
return Arrays.stream(Foo.class.getMethods()).
filter(method -> method.getReturnType() == Entity.class &&
Modifier.isStatic(method.getModifiers())).
map(method -> {
try {
return (Entity)method.invoke(null);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e); // exceptions in streams... lol
}
}).
collect(Collectors.toList());
}
I wish I knew a way to avoid the cast, but that's not immediately clear to me.

Here is the samele code for invoking specified methods of EntitiesForTest class and collect the return objects:
public static List<Entity> allEntities() {
ArrayList<Entity> list = new ArrayList<Entity>();
Method[] ma = EntitiesForTest.class.getMethods();
Object[] emptyObject = new Object[0];
for (int i = 0; i < ma.length; i++) {
if (ma[i].getReturnType().equals(Entity.class) &&
ma[i].getParameterTypes().length == 0 &&
Modifier.isStatic(ma[i].getModifiers())) {
try {
Entity e = (Entity)(ma[i].invoke(null, emptyObject));
list.add(e);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return list;
}

This answer makes several assumptions:
You don't need the individual methods (firstEntity, secondEntity, etc.)
The entities only hold data and are not expensive to create and keep around
You don't need to modify them, which means you wouldn't call your methods multiple times.
These might not hold, because we have no definition of Entity or how it's used.
All in all, I'm just removing your methods.
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class EntitiesForTest {
private static final List<Entity> entities = Arrays.asList(
new Entity(),
new Entity(),
new Entity()
);
public static Entity allEntities(int n) {
return entities.get(n);
}
public static List<Entity> allEntities() {
return Collections.unmodifiableList(entities);
}
}

Maybe using a functional way (in java 8 ) ?
public class Entities {
static class Entity{
private String x;
Entity( String x){
this.x = x;
}
public String getX(){
return x;
}
}
public static Entity firstEntity() {
return new Entity("first Entity");
}
public static Entity secondEntity() {
return new Entity("second Entity");
}
public static Entity nthEntity() {
return new Entity("nth Entity");}
#FunctionalInterface interface GetEntity{
public Entity getEntity();
}
public static List<GetEntity> allEntities =
Arrays.asList(Entities::firstEntity,
Entities::secondEntity,
Entities::nthEntity);
public static void main(String ...p){
allEntities
.stream()
.forEach(x->{System.out.println(x.getEntity().getX());});
}
}

Related

Create a neat method out of three similar ones using generics

I've tried to do some stuff with generics already but it seems I cannot personally find any simple solution. Still I think it'd be a sin to leave these 3 similar methods alone as they are.
public List<PassengerPlane> getPassengerPlanes() {
List<PassengerPlane> passengerPlanes = new ArrayList<>();
for (Plane plane : planes) {
if (plane instanceof PassengerPlane) {
passengerPlanes.add((PassengerPlane) plane);
}
}
return passengerPlanes;
}
public List<MilitaryPlane> getMilitaryPlanes() {
List<MilitaryPlane> militaryPlanes = new ArrayList<>();
for (Plane plane : planes) {
if (plane instanceof MilitaryPlane) {
militaryPlanes.add((MilitaryPlane) plane);
}
}
return militaryPlanes;
}
public List<ExperimentalPlane> getExperimentalPlanes() {
List<ExperimentalPlane> experimentalPlanes = new ArrayList<>();
for (Plane plane : planes) {
if (plane instanceof ExperimentalPlane) {
experimentalPlanes.add((ExperimentalPlane) plane);
}
}
return experimentalPlanes;
}
What do you need is generic method, but the problem is that instanceof cannot check against type parameter (it is in fact erased during compilation), it requires actual class reference. So, you may provide this to the method explicitly:
public <T extends Plane> List<T> getPlanes(Class<T> claz) {
List<T> result = new ArrayList<>();
for (Plane plane : planes) {
if (claz.isInstance(plane)) {
result.add(claz.cast(plane));
}
}
return result;
}
Note how instanceof and explicit cast changed to calls to .isInstance() and .cast()
Use it like
getPlanes(PassengerPlane.class)
You can make things a bit shorter with Streams, but I'm not sure there's a way to get around using instanceof here:
public List<PassengerPlane> getPassengerPlanes() {
return planes.stream().filter(t -> t instanceof PassengerPlane)
.map(t -> (PassengerPlane) t).collect(Collectors.toList());
}
public List<MilitaryPlane> getMilitaryPlanes() {
return planes.stream().filter(t -> t instanceof MilitaryPlane)
.map(t -> (MilitaryPlane) t).collect(Collectors.toList());
}
public List<ExperimentalPlane> getExperimentalPlanes() {
return planes.stream().filter(t -> t instanceof ExperimentalPlane)
.map(t -> (ExperimentalPlane) t).collect(Collectors.toList());
}
Here's how I would approach the problem using generics:
public <T> List<T> getTPlanes(Class<T> clazz) { //declare the method to take a type generic
List<T> tPlanes = new ArrayList<>(); //initialize an ArrayList of that type
planes.stream() //stream the planes list
.filter(clazz::isInstance) //filter it down to only planes of the type that we want
.forEach((p) -> tPlanes.add((T) p)); //add each plane left in the stream to our new ArrayList, and cast it to the type generic
return tPlanes; //return the ArrayList we just created and populated
}
You do need to do a cast somewhere: Here is a solution with a single method that takes the subtype.
import java.util.*;
import java.util.stream.*;
public class Example {
public static class Plane { }
public static class PassengerPlane extends Plane { }
public static class MilitaryPlane extends Plane { }
public static class ExperimentalPlane extends Plane { }
private static List<Plane> planes =
List.of(new PassengerPlane(),
new MilitaryPlane(),
new ExperimentalPlane());
public static <T extends Plane> List<T> getPlanesOfType(Class<T> type, List<Plane> planes) {
List<T> list =
planes.stream()
.filter(t -> type.isAssignableFrom(t.getClass()))
.map(t -> type.cast(t))
.collect(Collectors.toList());
return list;
}
public static void main(String[] args) throws Exception {
System.out.println(getPlanesOfType(PassengerPlane.class, planes));
System.out.println(getPlanesOfType(MilitaryPlane.class, planes));
System.out.println(getPlanesOfType(ExperimentalPlane.class, planes));
System.out.println(getPlanesOfType(Plane.class, planes));
}
}
[Example$PassengerPlane#7b227d8d]
[Example$MilitaryPlane#7219ec67]
[Example$ExperimentalPlane#45018215]
[Example$PassengerPlane#7b227d8d, Example$MilitaryPlane#7219ec67, Example$ExperimentalPlane#45018215]
You could either use the single method to replace all three or use it to implement.
If your problem is really so short, probably it won't be worthy the effort. However, this is a typical problem for Visitor Pattern (especially if your duplicate code is larger).
Step 1
Create a Visitor interface to visit each type of Plane:
interface Visitor {
void visit(MilitaryPlane militaryPlane);
void visit(ExperimentalPlane experimentalPlane);
void visit(PassengerPlane passengerPlane);
}
... and implement it in a way that starts with a List<Plane> that can be enriched by each of the .visit():
class PlaneVisitor implements Visitor {
private final List<Plane> planes;
PlaneVisitor(List<Plane> planes) {
this.planes = requireNonNull(planes);
}
#Override
public void visit(MilitaryPlane militaryPlane) {
planes.add(militaryPlane);
}
#Override
public void visit(ExperimentalPlane experimentalPlane) {
planes.add(experimentalPlane);
}
#Override
public void visit(PassengerPlane passengerPlane) {
planes.add(passengerPlane);
}
public List<Plane> getPlanes() {
return planes;
}
}
Step 2 - Enable visitors in your classes
Add an abstract method in your base class Plane to accept the visitor:
public abstract class Plane {
//...
abstract void accept(Visitor visitor);
//...
}
Then implement this method in each sub-class to let the Visitor instance visit itself (this). Example for PassengerPlane (same logic for all the other classes):
public class PassengerPlane extends Plane {
//...
#Override
void accept(Visitor visitor) {
visitor.visit(this);
}
//...
}
Step 3 - Adapt your function
Your function can now loop through the list of planes not caring about the type. It will be resolved by the visitor:
public List<Plane> getPlanes() {
PlaneVisitor planeVisitor = new PlaneVisitor(new ArrayList<>());
for (Plane plane : planes) {
plane.accept(planeVisitor);
}
return planeVisitor.getPlanes();
}
Note that you need to add a bit of methods / interfaces to do this. Since your code is very small, you can imagine to leave it like it is even if it's not very "elegant". However, the above example can be of inspiration if your code is actually supposed to do more than what you're showing us.
It can be done in this way by introduced a method that do common part:
private static <T> List<T> createFilteredList(List<Plane> inList, Class<T> clazz) {
List<T> outList = new ArrayList<>();
for (Plane value : inList) {
if (clazz.isInstance(value)) {
outList.add(clazz.cast(value));
}
}
return outList;
}
Then it can be used like this:
public List<PassengerPlane> getPassengerPlanes() {
return createFilteredList(planes, PassengerPlane.class);
}
public List<MilitaryPlane> getPassengerPlanes() {
return createFilteredList(planes, MilitaryPlane.class);
}
public List<ExperimentalPlane> getPassengerPlanes() {
return createFilteredList(planes, ExperimentalPlane.class);
}
So, you have an iterable of Plane as an input.
A Plane can be PassengerPlane, MilitaryPlane or ExperimentalPlane.
What you are trying to do is to filter a collection of planes by a predicate. A predicate is a function that takes a Plane and answers true or false. A filter uses a predicate to figure out whether to include a given item into the result or to skip.
If you are using Java 8 or later version, you can use the Streams API.
https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
Produce a stream from the planes iterable.
Apply filter to it (intermediate operation).
Collect the results to list.
Using Stream API you can convert the methods above into one-liners. Like this:
planes.stream().filter(plane -> plane instanceof MilitaryPlane).collect(toList());
Then, probably, you won't need a separate neat method for it.
But if you want some reusable piece of code, then you have to figure out what is the parameter here. In the code above it is a specific plane implementation:
public List<Plane> filterPlanes(Iterable<Plane> planes, Class<? extends Plane> planeImplementation)
So, you can build a predicate with this parameter:
plane -> planeImplementation.isInstance(plane)
If you have a Plane supertype, you can make the subclasses inherit the getPlanes() method. this.getClass will extract only the planes of the subclass calling the method from the list. This way, you don't have to pass a class to the method, as it can be derived from the subclass that is calling it.
public abstract class Plane {
public Plane(){}
public List<Plane> getPlanes() {
List<Plane> result = new ArrayList<>();
for (Plane plane : planes) {
if (this.getClass().isInstance(plane)) {
result.add(this.getClass().cast(plane));
}
}
return result;
}
}
class PassengerPlane extends Plane {
}
class MilitaryPlane extends Plane {
}
class ExperimentalPlane extends Plane {
}
public class PlaneList {
public String name;
public static ArrayList<Plane> planes = new ArrayList<>();
public PlaneList(){
planes.add(new MilitaryPlane());
planes.add(new MilitaryPlane());
planes.add(new MilitaryPlane());
planes.add(new PassengerPlane());
planes.add(new PassengerPlane());
planes.add(new ExperimentalPlane());
}
}
I tested it like so:
public class Main {
public static void main(String[] args) {
PlaneList list = new PlaneList();
Plane plane = new PassengerPlane();
for(Plane p : plane.getPlanes()){
System.out.println(p.toString());
}
}
}
output:
com.company.PassengerPlane#7dc36524
com.company.PassengerPlane#35bbe5e8

Avoid If-else code smell with creation of objects which depend upon specific conditions

Is there a better way to deal with an instanciation of an object (Product) which depends upon another object type (Condition) than using if-else paired with instanceof as the following code shows?
import java.util.ArrayList;
import java.util.List;
abstract class AbstractProduct {
private AbstractCondition condition;
public AbstractProduct(AbstractCondition condition) {
this.condition = condition;
}
public abstract void doSomething();
}
class ProductA extends AbstractProduct {
AbstractCondition condition;
public ProductA(AbstractCondition condition) {
super(condition);
}
#Override
public void doSomething() {
System.out.println("I'm Product A");
}
}
class ProductB extends AbstractProduct {
public ProductB(AbstractCondition condition) {
super(condition);
}
#Override
public void doSomething() {
System.out.println("I'm Product B");
}
}
class AbstractCondition { }
class ConditionA extends AbstractCondition { }
class ConditionB extends AbstractCondition { }
public class Try {
public static void main(String[] args) {
List<AbstractCondition> conditions = new ArrayList<AbstractCondition>();
List<AbstractProduct> products = new ArrayList<AbstractProduct>();
conditions.add(new ConditionA());
conditions.add(new ConditionB());
conditions.add(new ConditionB());
conditions.add(new ConditionA());
for (AbstractCondition c : conditions) {
tryDoSomething(c);
}
}
public static void tryDoSomething(AbstractCondition condition) {
AbstractProduct product = null;
if (condition instanceof ConditionA) {
product = new ProductA(condition);
} else if (condition instanceof ConditionB) {
product = new ProductB(condition);
}
product.doSomething();
}
}
The difference with the code above of my real code is: I have NO direct control over AbstractCondition and its subtypes (as they are in a library), but the creation of a concrete subtype of AbstractProduct depends on the concrete condition.
My goal being: try to avoid the if-else code smell in tryDoSomething().
I would also like to avoid reflection because it feels like cheating and I do think it's not an elegant, clean and readable solution.
In other words, I would like to tackle the problem just with good OOP principles (e.g. exploiting polymorphism) and pheraps some design patterns (which apparently I don't know in this specific case).
Since you can't edit the original objects, you need to create a static map from condition type to product type:
private static HashMap< Class<? extends AbstractCondition>,
Class<? extends AbstractProduct>
> conditionToProduct;`
Fill it in static initialization with the pairs of Condition,Product:
static {
conditionToProduct.put(ConditionA.class, ProductA.class);
...
}
and in runtime just query the map:
Class<? extends AbstractProduct> productClass = conditionToProduct.get(condition.getClass());
productClass.newInstance();
AbstractCondition needs to know either the type or how to construct a product.
So add one of the following functions to AbstractCondition
Class<? extends AbstractProduct> getProductClass()
or
AbstractProduct createProduct()
You should create a Factory class to help you with that then.
interface IFactoryProduct{
AbstractProduct getProduct(AbstractCondition condition) throws Exception;
}
This will be your interface, just need to implement it like this.
class FactoryProduct implements IFactoryProduct{
public AbstractProduct getProduct(AbstractCondition condition) throws Exception{
return (AbstractProduct)getClass().getMethod("getProduct", condition.getClass()).invoke(this, condition);
}
public ProductA getProduct(ConditionA condition){
return new ProductA();
}
public ProductB getProduct(ConditionB condition){
return new ProductB();
}
}
Using the reflexion to redirect with the correct method will do the trick. this is upgradable for subclassed if you want.
EDIT:
Some example :
List<AbstractCondition> list = new ArrayList<AbstractCondition>();
list.add(new ConditionA());
list.add(new ConditionB());
for(AbstractCondition c : list){
try {
System.out.println(f.getProduct(c));
} catch (Exception ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
labo.ProductA#c17164
labo.ProductB#1fb8ee3
A more complexe reflexion version allowing a subclass to be received :
public AbstractProduct getProduct(AbstractCondition condition) throws Exception{
Method m = getMethodFor(condition.getClass());
if(m == null )
throw new Exception("No method for this condition " + condition.getClass().getSimpleName());
else
return (AbstractProduct) m.invoke(this, condition);
}
private Method getMethodFor(Class<? extends AbstractCondition> clazz ) throws Exception{
try {
return getClass().getMethod("getProduct", clazz);
} catch (NoSuchMethodException ex) {
if(clazz.getSuperclass() != AbstractCondition.class){
return getMethodFor((Class<? extends AbstractCondition>)clazz.getSuperclass());
}
return null;
}
}
This allows me to send ConditionC extending ConditionB to build the same product has ConditionB would. Interesting for complexe heritage.

Mocking a DAO in Mockito

I'm just getting into testing of code. I have done unit tests before but haven't really isolated them. So they were more like integration test (indirectly). I want to give Mockito a try and I have added it to my Intellij IDE.
But I have no idea of how to actually implement mocking at all. There are examples on their website but I just can't wrap my head around the concept of mocking. I know that one uses mocking to isolate the unit testing to ensure that the errors are in the unit itself and not in a dependency.
I wrote the following:
#Test
public void testChangeMemberReturnsTrue() throws Exception {
Member tempMem = new Member();
tempMem.setMemberFirstName("Swagrid");
tempMem.setMemberLastName("McLovin");
tempMem.setMemberID("SM666");
SQLDUMMY.saveMember(tempMem); //Save member to dummy DB.
Member checkMem = new Member();
ArrayList<Member> memArr = SQLDUMMY.getAllMembers();
for (Member m : memArr) { // Look through all saved members
if (m.equals(tempMem)) { // If match, save to checkMem
checkMem = m;
}
}
assertTrue(tempMem.equals(checkMem)); // Make sure they are really equal.
String newfirstname = "Darius";
String newlastname = "DunkMaster";
assertTrue(memhandling.changeMember(tempMem, newfirstname, newlastname));
}
And here is the actual method:
public boolean changeMember(Member mem, String n1, String n2) {
try {
ArrayList<Member> memArr = SQLDUMMY.getAllMembers();
for (Member m : memArr) {
if (m.equals(mem)) {
m.setMemberFirstName(n1);
m.setMemberLastName(n2);
m.setMemberID(ensureUniqueID(m, m.getMemberID())); //Just a method call to another method in the same class to ensure ID uniqueness.
return true;
}
else {
return false;
}
}
}
catch (Exception e) {
System.out.println("Error4.");
}
return false;
}
I'd like to mock the SQLDUMMY (Which I created just to see if my tests would pass at all, which they do.) The SQLDUMMY class looks like this:
public class SQLDUMMY {
private static ArrayList<Member> memberList = new ArrayList<>();
private static ArrayList<Ship> shipList = new ArrayList<>();
public static ArrayList<Member> getAllMembers() {
return memberList;
}
public static void saveMember(Member m) {
memberList.add(m);
}
public static void deleteMember(Member memIn) {
memberList.remove(memIn);
}
public static void saveShip(Ship newShip) {
shipList.add(newShip);
}
public static ArrayList<Ship> getAllShips() {
return shipList;
}
public static void deleteShip(Ship s) {
shipList.remove(s);
}
}
It basically just consists of getters and add/remove for the ArrayLists that act as a contemporary DB storage.
Summary: How can I mock the SQLDUMMY class (DAO), so it is no longer a dependency for the Unit tests?
You need to read on how Mockito works.
The basic idea is that it extends you class and and overrides all methods and allows you to return what ever you want it too.
Syntax is :
SQLDummy sqlDummy = Mockito.mock(SQLDummy.class);
Mockito.when(sqlDummy.getAllShips()).thenReturn(new ArrayList< Ship >())

Class exporting iterators on two collections

Consider the case where a class contains two collections. Is it possible to provide iterators over both collections in a way that callers can use to iterate over?
My simple example:
public class Bar {
public static class Beer { /* ... */ }
public static class Wine { /* ... */ }
private Set<Beer> beers = new HashSet<Beer>();
private Set<Wine> wines = new HashSet<Wine>();
public Iterator<Beer> beerIterator() { return beers.iterator(); }
public Iterator<Wine> wineIterator() { return wines.iterator(); }
}
So far, so good. We can declare the methods that return the iterators, but the way I'm trying to do it, the caller can't use the iterator to, well, iterate.
void caller(Bar bar) {
for (Beer beer: bar.beerIterator()) { // <-- Compilation error: Can only iterate over an array or an instance of java.lang.Iterable
}
}
Any suggestions?
If the point in returning iterators is to protect your collections from changes while giving client ability to use foreach loops, then the most clear way will be to use Collections.unmodifiableSet wrapper. You can return it as Iterable interface to hide the implementation even further.
public static class Bar {
public static class Beer { /* ... */ }
public static class Wine { /* ... */ }
private Set<Beer> beers = new HashSet<Beer>();
private Set<Wine> wines = new HashSet<Wine>();
public Iterable<Beer> beerIterable() { return Collections.unmodifiableSet(beers); }
public Iterable<Wine> wineIterable() { return Collections.unmodifiableSet(wines); }
}
public static void main(String[] args) {
for (Bar.Beer beer : new Bar().beerIterable()) {
}
}
This approach is better than one suggested by #Tim Biegeleisen, because it protects your collection from being changed from outside. When you return .iterator of your original collection, client is still able to modify original collection by calling remove() method. Wrapping in unmodifiableSet prevents that.
However, be aware that client still can modify returned instances of Beer and Wine during the iteration, if they are mutable. If you want to be fully protected from changes, you need to make deep defensive copies of your collections before returning them to client.
The trick is to define 2 inner classes inside Bar which return custom iterators for beer and wine:
public class Bar {
public static class Beer { /* ... */ }
public static class Wine { /* ... */ }
private Set<Beer> beers = new HashSet<Beer>();
private Set<Wine> wines = new HashSet<Wine>();
private class Beers implements Iterable<Beer> {
#Override
public Iterator<Beer> iterator() {
return beers.iterator();
}
}
private class Wines implements Iterable<Wine> {
#Override
public Iterator<Wine> iterator() {
return wines.iterator();
}
}
public Beers beers() {
return new Beers();
}
public Wines wines() {
return new Wines();
}
}
You can use the custom iterators like this:
Bar bar = new Bar();
// add some beers and wines here
for (Beer beer : bar.beers()) {
System.out.println("Found another beer: " + beer);
}
for (Wine wine : bar.wines()) {
System.out.println("Found another wine: " + wine);
}

Type symbol not found in inner class

[EDIT: I've rewritten the code to further simplify it and focus on the issue at hand]
I'm working on this particular piece of code:
class SimpleFactory {
public SimpleFactory build() {return null}
}
class SimpleFactoryBuilder {
public Object build(final Class builderClazz) {
return new SimpleFactory() {
#Override
public SimpleFactory build() {
return new builderClazz.newInstance();
}
};
}
}
However, the builder in the return statement triggers the error "Cannot find symbol newInstance". It's as if builderClazz wasn't recognized as a class object.
How can I make it work?
EDIT: SOLUTION (thanks to dcharms!)
The code above is a partial simplification of the code I was dealing with. The code below is still simplified but includes all the components involved and includes the solution provided by dcharms.
package com.example.tests;
interface IProduct {};
interface ISimpleFactory {
public IProduct makeProduct();
}
class ProductImpl implements IProduct {
}
class SimpleFactoryBuilder {
public ISimpleFactory buildFactory(final Class productMakerClazz) {
return new ISimpleFactory() {
#Override
public IProduct makeProduct() {
try {
// the following line works: thanks dcharms!
return (IProduct) productMakerClazz.getConstructors()[0].newInstance();
// the following line -does not- work.
// return new productMakerClazz.newInstance();
}
catch (Exception e) {
// simplified error handling: getConstructors() and newInstance() can throw 5 types of exceptions!
return null;
}
}
};
}
}
public class Main {
public static void main(String[] args) {
SimpleFactoryBuilder sfb = new SimpleFactoryBuilder();
ISimpleFactory sf = sfb.buildFactory(ProductImpl.class);
IProduct product = sf.makeProduct();
}
}
You cannot instantiate a new object this way. builder is a Class object. Try instead the following:
return builder.getConstructors()[0].newInstance(anInput);
Note: this assumes you are using the first constructor. You may be able to use getConstructor() but I'm not sure how it would behave with the generic type.

Categories

Resources