How to replace switch with polymorphism? - java

I have 2 applications: application_1 and applicaion_2
appplication_1 sends messages of different types to application_2
there several types. I can declare enum of these types.
enum MessageType{
TYPE_1,
TYPE_2,
...
}
In application_2 framework I use suggest me write following API
public void handle(Object o){
//logic
}
I think about how to build classes to process each message separately.
I understand that I can declare common type for all messages:
abstract class AbstractMessage{
MessageType type;
Object o;
//...
}
and in application_2 inside handle I can write smth like this:
MessageType mt = ((AbstractMessage) o).getType();
switch(mt){
case TYPE_1:
//handle TYPE_1
break;
case TYPE_2:
//handle TYPE_2
break;
....
}
But this code looks ugly.
Please, help to find nicer solution.

If you want to use polymorfism you could define the abstract message class:
abstract class AbstractMessage {
public abstract void doStuff();
//...
}
instead of using enums, create a class for each message type extending the abstract class and overriding the methods:
class Type1Message extends AbstractMessage {
#Override
public void doStuff() {
//handle TYPE_1
}
}
class Type2Message extends AbstractMessage {
#Override
public void doStuff() {
//handle TYPE_2
}
}
then in your handle method:
((AbstractMessage) o).doStuff();

application_2 anyway will need to know which type of message it has received, so some kind of switch is unavoidable. But the key thing is to have this switch only at one place. For example, you could have method like following:
public MessageHandler getHandlerFor(MessageType messageType) {
switch (messageType) {
case TYPE_1: return Type1MessageHandler();
case TYPE_2: return Type2MessageHandler();
............
default: throw new IllegalArgumentException("No handler found for messageType: " + messageType);
}
}
Then you will need the hierarchy of MessageHandler's which correspond to strategy pattern:
public interface MessageHandler {
void handle();
}
Each implementation of MessageHandler interface should provide MessageType-specific handling logic.

You can use the chain-of-responsibility pattern. It differs from the strategy pattern in that your messages are indicating commands that each application performs. This is essentially what switch is doing.
You dynamically load classes that implement an interface with your handle method (Pavlo's class works with some modification to combine it with Loris' abstract message):
public interface MessageHandler
{
void handle (AbstractMessage msg);
}
Java has the concept of a service provider that is one method for dynamic loading (I'm sure there are other methods that can be used if this doesn't fit your need). You can iterate through the handlers at the time the message is handled, passing each handler the message instance. Each handler decides if it wants to handle the message or not. You could even make handle return a boolean to indicate that the chain can stop calling subsequent handlers if you so wish.
You can implement handlers in each application for the message types you want to handle. There are many ways to go about this (load the handlers and initialize each at startup, load them at time of message handling, etc) so pick the one that fits your need. The linked service providers article has a simple loop demonstrating the loading of the handlers.
No need for a switch that changes as your code is modified, you just reconfigure how your jar is built. This is also a good example of the open-closed principle where your code does not change but is open to extension.

maybe something like below. it does have a switch, but the code for each type is together in the enum.
public class So43459907 {
public enum Type {
m1 {
#Override Object create(Object o) {
return o;
}
#Override void handle(Object o) {}
},
m2 {
#Override Object create(Object o) {
return o;
}
#Override void handle(Object o) {}
};
abstract Object create(Object o);
abstract void handle(Object o);
public static Object create(Type type,Object o) {
switch(type) {
case m1:
return m1.create(o);
case m2:
return m2.create(o);
default:
throw new RuntimeException("oops");
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}

Related

Default/Mixin Generic In java

I am wondering if i can replace the generic type upon class initialization ( without inheritance ).
The case is as below .
I have bunch of generic actor + builder class in my module and distribute this to people who wants to use it in my team while keeping the actor and the entry point of fluent interface generic.
The requirement is how can people supply their own builder ( not extending ) to do the stuff they want.
Current state:
class MessageBuilder {
public MessageBuilder msg(String msg) {
//do something
}
}
class Actor {
public MessageBuilder newMessage() {
return new MessageBuilder();
}
}
class Main {
#Test
public void testActor() {
Actor actor = new Actor();
actor.newMessage().msg("sss").send();
}
}
Desired state:
class MessageBuilder{
public MessageBuilder msg(String msg) {
//do something
}
//more fluent api...
}
// project specific - dont want to extend from generic one as this should be contains its own fluent interface
class MyCustomMessageBuilder {
public MyCustomMessageBuilder rawstr(String rawstr) {
//do something
}
}
class Actor<T> {
public T newMessage() {
return (T)builderFactory.getInstance();
}
}
class Main {
#Test
public void testActor() {
Actor<MyCustomMessageBuilder> actor = new Actor(BuilderFactory);
actor.newMessage().rawstr("sss").send();
}
}
It's not possible without some known tricks.
First, Java implements Generics with type erasure (more information on type erasure), therefore the compiler will:
Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
In practice, this means that Actor<Builder1> and Actor<Builder2> are the exact same class after it gets compiled. In both cases, newMessage is implemented as follows:
class Actor {
public Object newMessage() {
...
}
}
It's not possible for newMessage to have different implementations based on the type parameter and it's not possible for newMessage to ask for the type of T because it gets removed.
Having said that, you can pass in type information:
class Actor<T> {
private Class<T> klass;
public Actor(Class<T> klass) {
this.klass = klass;
}
public T newMessage() {
return klass.newInstance();
}
}
class Main {
#Test
public void testActor() {
Actor<MyCustomMessageBuilder> actor = new Actor<>(MyCustomMessageBuilder.class);
actor.newMessage().rawstr("sss").send();
}
}
I'd go with a factory approach. The builder should be supplied by a factory:
class Actor<MsgBuilder> {
private final Supplier<MsgBuilder> messageBuilderFactory;
public Actor(Supplier<MsgBuilder> builderFactory) {
this.messageBuilderFactory = builderFactory;
}
public MsgBuilder newMessage() {
return messageBuilderFactory.get();
}
}
This way offers flexibility in creating the message builder without sacrificing type safety and also no need for ugly casting.

Clean code for removing switch condition(using polymorphism)

As SOLID principles say, it's better to remove switch conditions by converting them to classes and interfaces.
I want to do it with this code:
Note: This code is not real code and I just put my idea into it.
MessageModel message = getMessageFromAnAPI();
manageMessage(message);
...
void manageMessage(MessageModel message){
switch(message.typeId) {
case 1: justSave(message); break;
case 2: notifyAll(message); break;
case 3: notify(message); break;
}
}
Now I want to remove switch statement. So I create some classes for it and I try to implement a polymorphism here:
interface Message{
void manageMessage(MessageModel message);
}
class StorableMessage implements Message{
#Override
public void manageMessage(MessageModel message) {
justSave(message);
}
}
class PublicMessage implements Message{
#Override
public void manageMessage(MessageModel message) {
notifyAll(message);
}
}
class PrivateMessage implements Message{
#Override
public void manageMessage(MessageModel message) {
notify(message);
}
}
and then I call my API to get my MessageModel:
MessageModel message = getMessageFromAnAPI();
Now my problem is here. I have my model and I want manage it using my classes. As SOLID examples, I should do something like this:
PublicMessage message = new Message();
message.manageMessage(message);
But how can I know which type is related to this message to make an instance from it(PublicMessage or StorableMessage or PrivateMessage)?! Should I put switch block here again to do it or what?
You can do this:
static final Map<Integer,Consumer<MessageModel>> handlers = new HashMap<>();
static {
handlers.put(1, m -> justSave(m));
handlers.put(2, m -> notifyAll(m));
handlers.put(3, m -> notify(m));
}
This will remove your switch to
Consumer<Message> consumer = handlers.get(message.typeId);
if (consumer != null) { consumer.accept(message); }
Integration Operation Segregation Principle
You should of course encapsulate this:
class MessageHandlingService implements Consumer<MessageModel> {
static final Map<Integer,Consumer<MessageModel>> handlers = new HashMap<>();
static {
handlers.put(1, m -> justSave(m));
handlers.put(2, m -> notifyAll(m));
handlers.put(3, m -> notify(m));
}
public void accept(MessageModel message) {
Consumer<Message> consumer = handlers.getOrDefault(message.typeId,
m -> throw new MessageNotSupportedException());
consumer.accept(message);
}
}
with your client code
message = getMessageFromApi();
messageHandlingService.accept(message);
This service is the "integration" part (as opposed to the "implementation": cfg Integration Operation Segregation Principle).
With a CDI framework
For a production environment with a CDI framework, this would look something like this:
interface MessageHandler extends Consumer<MessageModel> {}
#Component
class MessageHandlingService implements MessageHandler {
Map<Integer,MessageHandler> handlers = new ConcurrentHashMap<>();
#Autowired
private SavingService saveService;
#Autowired
private NotificationService notificationService;
#PostConstruct
public void init() {
handlers.put(1, saveService::save);
handlers.put(2, notificationService::notifyAll);
handlers.put(3, notificationService::notify);
}
public void accept(MessageModel m) { // as above }
}
Behavior can be changed at Runtime
One of the advantages of this vs the switch in #user7's answer is that the behavior can be adjusted at runtime. You can imagine methods like
public MessageHandler setMessageHandler(Integer id, MessageHandler newHandler);
which would install the given MessageHandler and return the old one; this would allow you to add Decorators, for example.
An example for this being useful is if you have an unreliable web service supplying the handling; if it is accessible, it can be installed as a handlelr; otherwise, a default handler is used.
You can use a factory in this case to get the instance of Message. The factory would have all instances of Message and returns the appropriate one based on the MessageModel's typeId.
class MessageFactory {
private StorableMessage storableMessage;
private PrivateMessage privateMessage;
private PublicMessage publicMessage;
//You can either create the above using new operator or inject it using some Dependency injection framework.
public getMessage(MessageModel message) {
switch(message.typeId) {
case 1: return storableMessage;
case 2: return publicMessage;
case 3: return privateMessage
default: //Handle appropriately
}
}
}
The calling code would look like
MessageFactory messageFactory; //Injected
...
MessageModel messageModel = getMessageFromAnAPI();
Message message = messageFactory.getMessage(messageModel);
message.manageMessage(messageModel);
As you can see, this did not get rid of the switch entirely (and you need not as using switch is not bad in itself). What SOLID tries to say is to keep your code clean by following SRP (Single Responsibility Principle) and OCP (Open-Closed Principle) here. What it means here is that you code shouldn't have the actual processing logic to handle for each typeId in one place.
With the factory, you have moved the creation logic to a separate place and you have already moved the actual processing logic to respective classes.
EDIT:
Just to reiterate - My answer focuses on the SOLID aspect of the OP. By having separate handler classes (an instance of Message from the OP) you achieve the SRP. If one of the handler classes changes, or when you add a new message typeId (message.typeId) (i.e, add a new Message implementation) you need not modify the original and hence you achieve OCP. (On assumption that each of these does not contain trivial code). These are already done in the OP.
The real point of my answer here is to use a Factory to get a Message. The idea is to keep the main application code clean and limit the usages of switches, if/else and new operators to instantiation code. (Similar to #Configuration classes/ the classes that instantiate Beans when using Spring or Abstract modules in Guice). The OO principles do not say using switches are bad. It depends on where you use it. Using it in the application code does violate the SOLID principles and that is what I wanted to bring out.
I also like the idea from daniu# to use a functional way and the same can even be used in the above factory code (or can even use a simple Map to get rid of the switch).
The main point here is that you separate instantiation and configuration from execution.
Even with OOP we cannot avoid to distinguish between different cases using if/else cascades or switch statements. After all we have to create instances of specialized concrete classes.
But this should be in initialization code or some kind of factory.
Within the business logic we want to avoid if/else cascades or switch statements by calling generic methods on interfaces where the implementer know better themselves how to behave.
The usual clean code approach is for the MessageModel to contain its behavior.
interface Message {
void manage();
}
abstract class MessageModel implements Message {
}
public class StoringMessage extends MessageModel {
public void manage() {
store();
}
}
public class NotifyingMessage extends MessageModel {
public void manage() {
notify();
}
}
Your getMessageFromApi then returns the proper type, and your switch is
MessageModel model = getMessageFromApi();
model.manage();
This way, you essentially have the switch in the getMessageFromApi() method because it has to decide which message to generate.
However, that is fine because it does fill the message type id anyway; and the client code (where your switch currently resides) is resistent to changes to the messages; ie adding another message type will be be handled correctly.
The real problem you have is that MessageModel isn't polymorphic. You need to convert the MessageModels to a polymorphic Message class, but you shouldn't put any of the logic of what to do with the messages in this class. Instead, it should contain the actual contents of the message, and use the visitor pattern, as shown in Eric's Answer, so that other classes can operate on a Message. You don't need to use an anonymous Visitor; you can create implementing classes like a MessageActionVisitor.
To convert MessageModels to various Messages, you can use a factory, as shown in user7's answer. In addition to selecting which type of Message to return, the factory should fill in the fields of each type of Message using the MessageModel.
You can use the Factory Pattern. I would add an enum which has the values:
public enum MessageFacotry{
STORING(StoringMessage.TYPE, StoringMessage.class),
PUBLIC_MESSAGE(PublicMessage.TYPE, PublicMessage.class),
PRIVATE_MESSAGE(PrivateMessage.TYPE, PrivateMessage.class);
Class<? extends Message> clazz;
int type;
private MessageFactory(int type, Class<? extends Message> clazz){
this.clazz = clazz;
this.type = type;
}
public static Message getMessageByType(int type){
for(MessageFactory mf : values()){
if(mf.type == type){
return mf.clazz.newInstance();
}
}
throw new ..
}
}
Then you can call the static method of that enum and create an instance of the Message you want to manage.
You can use the Factory pattern and Visitor pattern together.
you can create a factory like this:
class MessageFactory {
public Message getMessage(MessageModel message) {
switch(message.typeId) {
case 1: return new StorableMessage((MessageModelType1) message);
case 2: return new PrivateMessage((MessageModelType2) message);
case 3: return new PublicMessage((MessageModelType3) message);
default: throw new IllegalArgumentException("unhandled message type");
}
}
}
and declare your messages like this:
interface Message {
void accept(Visitor visitor);
}
class StorableMessage implements Message {
private final MessageType1 message;
public StorableMessage(MessageModelType1 message) {
this.message = message;
}
#Override
public <Result> Result accept(Visitor<Result> visitor) {
return visitor.visit(this);
}
public MessageModelType1 getMessage() {
return message;
}
}
class PublicMessage implements Message {
...
}
class PrivateMessage implements Message {
...
}
and declare a Visitor like this:
interface Visitor {
void visit(StorableMessage message);
void visit(PublicMessage message);
void visit(PrivateMessage message);
}
and replace your switch statements with this:
Message message = ....;
message.accept(new Visitor() {
#Override
public void visit(StorableMessage message) {
justSave(message.getMessage());
}
#Override
public void visit(PublicMessage message) {
notifyAll(message.getMessage());
}
#Override
public void visit(PrivateMessage message) {
notify(message.getMessage());
}
});
If you want, instead of writing an anonymous class, you can create a class MessageModelFactory that has a private Visitor, and use that instead. in that case, it might be better to make the Visitor interface like this:
interface Visitor<Result> {
Result visit(StorableMessage message);
Result visit(PublicMessage message);
Result visit(PrivateMessage message);
}

Are parametrized and unparametrized versions of the same interface possible in Java?

Question
If one defines a public class Something <T> { ... }, then Java will complain about using a raw type if you do this: Something noparam = new Something();
Is it possible to define an interface or class that can be used with or without a type parameter?
Context
The frontend of a Java app interfaces asynchronously with our backend using callbacks:
public interface ResultCallback <T> {
public void onResult(T result);
public void onError();
}
Here's an example of the backend I'm talking about, with some basic CRUD operations using the callback above:
public interface Backend {
// create a new Comment for a specified blog Post
public void createComment(Post post, ResultCallback<Comment> callback);
// retrieve the Comment with the specified UUID
public void getComment(UUID id, ResultCallback<Comment> callback);
// delete the Comment with the specified UUID
public void deleteComment(UUID id, ResultCallback callback);
}
Notice that the delete operation's callback.onResult(T result) will not have a Comment parameter. It might make sense to parametrize that result with a Comment and just "return" the deleted Comment, even if it's just to satisfy the type parameter constraint of ResultCallback. I don't like this idea because the Comment is gone from the backend and no changes to it will persist.
Just for a usage example, the idea is that ResultCallbacks are defined in the frontend of the app and passed to the async backend. For example, to display a comment:
public CommentRenderer implements ResultCallback<Comment> {
#Override
public void onResult(Comment comment) {
// display the comment, commenter, date, etc. on screen
}
#Override
public void onError(String message) {
// display an error message
}
}
No, the closest thing to that comes to mind would be to use ResultCallback<Void> but that would still require you to give the onResult a null-argument which is kind of ugly.
In this case I would recommend you to either use a separate interface for the delete case or let ResultCallback have more than one method:
interface ResultCallback<T> {
void onResult(T t);
void onDelete(); // Called after delete.
void onError(String message);
}
If you think it is frustrating to override the onDelete even though you're rarely interested in "listening" for these type of events, you could give it an empty default implementation:
...
default void onDelete() {
// do nothing by default
}
...
An alternative for pre-Java 8, is to use an Adapter which would look like follows:
abstract class ResultAdapter<T> implements ResultCallback<T> {
#Override
public void onResult(T t) {
}
#Override
public void onDelete() {
}
#Override
public void onError(String msg) {
}
}
You can always use ResultCallback<Void> and use null in that case.
How a bout extended Generic Type?
public class Foo<T extends Comment> { ... }
public class FooDefault extends Foo< Baz > { ... }

Calling different services from domain classes of same base class

The question is mostly a design question (somewhat related to ddd). Sorry about the contrived example:
Assume, you have (domain) classes representing different types of fruits: apple, cherry and so on. Now suppose you have to implement some behavior of pressing out the juice. A caller should be able to invoke squeezing without knowing which specific fruit he's got.
Where should I put this behavior?
Surely, one could define a fruit interface / base class function
Fruit#squeeze()
and let all subclasses implement their own behavior.
Now a caller could simply do something like this:
Fruit f = new Cherry();
f.squeeze();
But what should be done if squeezing isn't as simple and involves more complex behavior like calling different external services, for each a fruit a different one like
AppleJuicerService#squeeze(Apple a)
and
CherryJuicerService#squeeze(Cherry c)
? It feels wrong to call services from a domain class.
I've read about the double dispatch pattern which seems not to fit here, as every subclass needs a different service.
My question would be: What can be done here to get a "clean" design?
EDIT:
Thanks for all your answers so far. I'll try to clarify the problem a bit. I'll try to give another, hopefully less contrived example for the problem I'm trying to state here:
Consider a Message base class which allows to show its content as a String.
interface Message {
String showContent();
}
Now suppose we have different types of messages like an EMailMessage:
class EMailMessage implements Message {
//some specific parameters for email
private EmailAddress recipientEmail;
public String showContent() {
//here the content would be converted to string
return "the content of an EMail"
}
}
Another type would be an SMSMessage:
class SMSMessage implement SMSMessage {
//some specific parameters for SMS
private TelNumber recepientTelephoneNumber;
public String showContent() {
//here the content would be converted to string
return "the content of a SMS"
}
}
Furthermore suppose, Messages are modeled as Entities and therefore can be persisted in a database. Though quite technically, assume that some Dependency Injection Framework like Spring is used to inject dependencies.
In analogy to the fruit example, consider we have to implement a send() behaviour which sends the Message to the recipient. Furthermore, assume that sending an EMail involves different logic than an SMS. Now, the question: Where should one put the logic of sending a Message?
Usually I'd opt to create a service for sending an SMS for example which would encapsulate e.g. the API of an SMS service provider. Furthermore, I'd create another service to encapsulate sending an EMail.
interface SendMessageService<T extends Message> {
void send(T message);
}
class SendEmailService extends SendMessageService<EMailMessage> {
public void send(EMailMessage message) {
//send the EMail
}
}
class SendSMSService extends SendMessageService<SMSMessage> {
public void send(SMSMessage message) {
//send the SMS
}
}
The drawback of this approach is that you cannot send a Message without determining its concrete subclass, i.e. something like the following is not directly possible
List<Message> messages = //Messages of different types
SendMessageService service = //???
for (Message m : messages) {
service.send(m);
}
Surely one could create a factory for creating Services according to the specific type of message. But that somewhat means cloning the inheritance hierarchy of Message. Is there some better way to achieve the desired result? Or am I missing something? Or would it be better to somehow inject the service into the entity?
You can delegate the work to a SqueezeBehavior interface and let each implementation define how to squeeze a Fruit or specific Fruit. This is a raw idea (it means it can be improved but is good as a first step):
interface SqueezeBehavior<T> {
void squeeze(T squeezeMe);
}
interface FruitSqueezeBehavior<T extends Fruit> extends SqueezeBehavior<T> {
}
class FruitSqueezer implements FruitSqueezeBehavior<Fruit> {
public void squeeze(Fruit fruit) {
System.out.println("squizing any fruit");
}
}
class AppleSqueezer implements FruitSqueezeBehavior<Apple> {
public void squeeze(Apple apple) {
System.out.println("squizing apple");
}
}
class CherrySqueezer implements FruitSqueezeBehavior<Cherry> {
public void squeeze(Cherry cherry) {
System.out.println("squizing cherry");
}
}
class FruitService {
public void foo(Fruit fruit) {
FruitSqueezeBehavior fruitSqueezer = ...
fruitSqueezer.squeeze(fruit);
}
}
Have a baseclass Fruit which defines the standard behaviour. When you have to use a more complex implementation you can override the appropriate method.
class Fruit {
public void Squeeze(){
// Standard squeeze behaviour
}
}
class Apple extends Fruit {
#Override
public void Squeeze(){
// Complex squeeze behaviour
}
}
class Cherry extends Fruit {
// Nothing special, cherries are easy to squeeze
}
If you have to define specific implementations for specific types, you will always have to define the behaviour somewhere. If this is too much for one method then you can call a more detailed class to do it for you.
You could work with a factory and do something like this
class FruitManipulator {
void Squeeze(Fruit f){
// Switch over fruit, create new service depending on the type
}
}
interface JuiceService<T extends Fruit> {
void Squeeze(T f);
}
class AppleJuiceService implements JuiceService<Apple> {
void Squeeze(Apple apple){
// Do your thing
}
}
And use it like this:
FruitManipulator service = new FruitManipulator();
service.Squeeze(new Apple());
You might want to find a better example though: the Squeeze() analogy isn't easy to work with. Perhaps expand on what a squeeze actually means?
You may consider DomainEvents. This helps you decouple Domain models from external service(usually stateless bean need injected)
interface Fruit {
void squeeze();
}
class Apple implements Fruit {
#Override
public void squeeze(){
// domain rules validations
DomainEvents.raise(new AppleSequeezedEvent(this));
}
}
class Cherry extends Fruit {
#Override
public void squeeze(){
// domain rules validations
DomainEvents.raise(new CherrySequeezedEvent(this));
}
}
class Banana extends Fruit {
#Override
public void squeeze(){
// domain rules validations
// hmm...No one cares banana...
}
}
class DomainEvents {
private static List<DomainEventHandler> handlers = new ArrayList<DomainEventHandler>();
public static void register(DomainEventHandler handler) {
this.handler.add(handler);
}
public static void raise(DomainEvent event) {
for (DomainEventHander handler: handlers) {
if (handler.subscribe(event.getClass()) {
handler.handle(event);
}
}
}
}
Now when you test apple, you could register some handler mock/stub:
#Test
public void tellsAppleIsSqueezed() throws Throwable {
DomainEventHandler stub = new FruitSqueezedEventHandlerStub(Apple.class);
DomainEvents.register(stub );
Apple apple = new Apple();
apple.squeeze();
//assert state change of apple if any before you publishing the event
assertThat(stub.getSqueezed(), sameInstance(apple));
}
You can test the real handler in their own unit test cases.
But I think this solution add extra complexity.

Design question - java - what is the best way to doing this?

I have a design problem.
I have two data objects which are instances of say class A and class B.
A and B don't have any behavior - they are java beans with getters and setters.
I have a Validation interface and 10 implementations of it defining different Validations.
I would like to specify in my properties file which Validation applies to which class.
Something like this:
class A XYZValidation,ABCValidation
class B: ABCValidation, PPPValidation, etc
How do I write my Validation class so that it serves objects that are instances of Class A OR ClassB, or just about any other Class C that I might want to add in future?
interface Validation {
public boolean check(??);
}
> Just wanted to add this line to say thank you to all those who have responded to this post and to say that I am loving my time here on this amazing website. Stackoverflow rocks!
Have you thought about using annotations to mark the fields you want to validate in your bean?
If you have 10 different validations you could specify 10 annotations. Then mark the fields using annotations:
#ValideStringIsCapitalCase
private String myString;
#ValidateIsNegative
private int myInt;
With reflection API iterate through all the fields and see if they are marked, something like this:
public static <T> validateBean(T myBean) throws IllegalAccessException {
Field[] fields = myBean.getClass().getDeclaredFields();
// This does not take fields of superclass into account
if (fields != null) {
for (Field field : allFields) {
if (field.isAnnotationPresent(ValideStringIsCapitalCase.class)) {
field.setAccessible(true);
Object value = field.get(existingEntity);
// Validate
field.setAccessible(false);
}
}
}
}
An option would be to mark the whole class with the validator you want to use.
EDIT: remember to include annotation:
#Retention(RetentionPolicy.RUNTIME)
for your annotation interface.
EDIT2: please don't modify the fields directly (as in the example above). Instead access their getters and setters using reflection.
I've probably misunderstood the question but would something like this suffice:
public class ValidationMappings {
private Map<Class, Class<Validation>[]> mappings = new HashMap<Class, Class<Validation>[]>();
public ValidationMappings() {
mappings.put(A.class, new Class[]{XYZValidation.class, ABCValidation.class});
mappings.put(B.class, new Class[]{ABCValidation.class, PPPValidation.class});
}
public Class[] getValidators(Class cls) {
if (!mappings.containsKey(cls)) return new Class[]{};
return mappings.get(cls);
}
}
When you want to get the list of validators for a particular class, you would then call getValidators(Class cls) and iterate over each validator and create an instance of each and call your check method.
something like this maybe?
interface Validation {
public boolean check(Validatable x);
}
interface Validatable {
}
class A implements Validatable {
...
}
class Validator {
public boolean validateObject(Validatable x){
boolean validated = true;
... //read config file, check which validation classes to call
//for each validation class v in the config file:
if(!v.check(x)) validated = false;
return validated;
}
}
If you just want it to deal with any object then it'll be Object's that your interface
public boolean check(Object o);
Unless you want to use some marker interface to tag classes that are suitable for validation
Did you mean:
public interface Validation<T> {
boolean check(T object)
}
First of all, I'd use the following interface
interface Validator {
boolean isValid(Object object);
}
to implicitly document what the return value actually means.
Secondly, I'd suggest to document in the interface what behavior is expected if the Validator doesn't know how to handle the given instance.
interface Validator {
/**
* #return false if this validator detects that the given instance is invalid, true if the given object is valid or this Validator can't validate it.
*/
boolean isValid(Object object);
}
That way, you'd simply have a List of Validators that you could throw your objects at.
The performance impact of incompatible Validators should be negligible if they are implemented properly, e.g. with an early instanceof.
On a side note, I'd use a List of Validators instead of a Set so you can order them according to complexity. Put the cheap (performance-wise) Validators at the start of the List as an optimization.
You could then use a general piece of code for validation, e.g.
public class Validators {
public static boolean isValid(Object o, Collection<Validator> validators) {
for(Validator current : validators) {
if(!current.isValid()) return false;
}
return true;
}
}
Depending on your use-case it might be a good idea to return something different than boolean in your interface. If you need information about what is wrong, e.g. to display it, you'd need to return that info instead.
In that case it might be a good idea to keep the above loop running so you'll get all validation errors instead of only the first.
A Visitor pattern would solve this
Calling the Visitor Validator it's possible to have this:
public interface Validatable {
public boolean validate(Validator v);
}
public interface Validator {
public boolean validate(A a);
public boolean validate(B b);
}
public class A implements Validatable {
public boolean validate(Validator v){
return v.validate(this);
}
}
public class B implements Validatable {
public void validate(Validator v) {
return v.validate(this);
}
}
// Default validator just doesn't know how to
// validate neither A's, nor B's
public class GenericValidator implements Validator {
public boolean validate(A a) {
throw new UnsupportedOperationException("Cannot validate A");
}
public boolean validate(B b) {
throw new UnsupportedOperationException("Cannot validate B");
}
}
// since XYZValidation is supposed to run only on A's
// it only overrides A validation
public class XYZValidation extends GenericValidator {
public boolean validate(A a) {
// validate a
return isVAlid(a);
}
}
// since ABCValidation is supposed to run on A's and B's
// it overrides A and B validation
public class ABCValidation extends GenericValidator {
public boolean validate(A a) {
// validate a
return isVAlid(a);
}
public boolean validate(B b) {
// validate b
return isVAlid(b);
}
}
// since ABCValidation is supposed to run only on B's
// it overrides A only B validation
public class PPPValidation extends GenericValidator {
public boolean validate(B b) {
// validate b
return isVAlid(b);
}
}

Categories

Resources