spring state machine - manage long running processes - java

I need some advice for using spring state machine for long running processes. I want to design some flow. Let's say I have next states: Start->step1->step2->step3->finish. I have a controller that can send events to the state machine for managing transitions between states. I have a StateMachinePersister. I have a converter from StateMachineContext to byte[] and back. Sounds good for my business goal. So everything should work fine.
But I have a problem? I can't understand how to manage cases when I will decide to change the flow. I mean that if I have a Production environment where some processes persisted in "step2" state. But I am forced to change the flow. let say that I want to add a step or remove a step in the flow. I think I will have problems during state machine deserialization.
So the question is: may be spring state machine is not suitable for me, or there are some recipes how I can manage such cases?
I have an entity which I want to manage states, transitions etc.
#Entity
#Access(AccessType.FIELD)
#Table(name = "processes", indexes = #Index(columnList = "currentState"))
public class Process extends AbstractPersistable<Long> implements ContextEntity<ProcessState, ProcessEvent, Long> { // NOSONAR
private static final long serialVersionUID = 8848887579564649636L;
#JsonIgnore
StateMachineContext<ProcessState, ProcessEvent> stateMachineContext; // NOSONAR
#Enumerated(EnumType.STRING)
ProcessState currentState;
#Override
public void setStateMachineContext(StateMachineContext<ProcessState, ProcessEvent> stateMachineContext) {
if (stateMachineContext == null) {
throw new IllegalStateException("stateMachineContext can't be null");
}
this.currentState = stateMachineContext.getState();
this.stateMachineContext = stateMachineContext;
}
#Override
public StateMachineContext<ProcessState, ProcessEvent> getStateMachineContext() {
return stateMachineContext;
}
...
}
I have StateMachinePersist bean which is responsible for initializing stateMachineContext for particular process.
#Bean
public StateMachinePersist> persist() {
return new StateMachinePersist>() {
#Override
public StateMachineContext<ProcessState, ProcessEvent> read(
ContextEntity<ProcessState, ProcessEvent, Serializable> process) throws Exception {
return process.getStateMachineContext();
}
#Override
public void write(StateMachineContext<ProcessState, ProcessEvent> context,
ContextEntity<ProcessState, ProcessEvent, Serializable> process) throws Exception {
process.setStateMachineContext(context);
}
};
}
I have StateMachineAdapter which is responsible for persisting and restoring state machine
public class DefaultStateMachineAdapter<S, E, T> {
final StateMachineFactory<S, E> stateMachineFactory;
final StateMachinePersister<S, E, T> persister;
public DefaultStateMachineAdapter(StateMachineFactory<S, E> stateMachineFactory, StateMachinePersister<S, E, T> persister) {
this.stateMachineFactory = stateMachineFactory;
this.persister = persister;
}
public StateMachine<S, E> restore(T contextObject) throws Exception {
StateMachine<S, E> stateMachine = stateMachineFactory.getStateMachine();
return persister.restore(stateMachine, contextObject);
}
public void persist(StateMachine<S, E> stateMachine, T order) throws Exception {
persister.persist(stateMachine, order);
}
public StateMachine<S, E> create() {
StateMachine<S, E> stateMachine = stateMachineFactory.getStateMachine();
stateMachine.start();
return stateMachine;
}
}
I have StateMachineContextConverter which is responsible for serialization/deserialization of StateMachineContext. I have used Kryo for this operations.
public class StateMachineContextConverter implements AttributeConverter<StateMachineContext, byte[]> {
#Override
public byte[] convertToDatabaseColumn(StateMachineContext attribute) {
return serialize(attribute);
}
#Override
public StateMachineContext convertToEntityAttribute(byte[] dbData) {
return deserialize(dbData);
}
}
I have controller which is responsible to switch states
public class ProcessEventController {
final DefaultStateMachineAdapter<ProcessState, ProcessEvent, ContextEntity<ProcessState, ProcessEvent, ? extends Serializable>> processStateMachineAdapter;
public ProcessEventController(DefaultStateMachineAdapter<ProcessState, ProcessEvent, ContextEntity<ProcessState, ProcessEvent, ? extends Serializable>> processStateMachineAdapter) {
this.processStateMachineAdapter = processStateMachineAdapter;
}
#RequestMapping(path = "/processes/{id}/{event}", method = RequestMethod.POST)
#Transactional
public HttpEntity<Void> receiveEvent(#PathVariable("id") Process process, #PathVariable("event") ProcessEvent event) throws Exception {
StateMachine<ProcessState, ProcessEvent> stateMachine = processStateMachineAdapter.restore(process);
if (stateMachine.sendEvent(event)) {
processStateMachineAdapter.persist(stateMachine, process);
return ResponseEntity.accepted().build();
} else {
return ResponseEntity.unprocessableEntity().build();
}
}
}

Obviously you can't modify existing running machine but as you're already working with persistence I assume you're at least stopping machines.
Look statemachine-examples-datajpa which is using existing machine apis to store config in a DB. We have StateMachineModelFactory which pretty much allows you to store your stuff anywhere if any build-in implementation is not suitable for you. This sample will build new machine instances every time when new events are sent. i.e. you can go to a DB using build-in editor and add new transition(s) without restarting a main java process.
This gives you some flexibility but if you need to change your running code then things will get impossible.

Related

Design pattern suggestion to perform pipeline operation

Problem statement:
I have to process request similar to a pipeline.
For example:
When a request comes, it has to undergo a sequence of operations, like (step1,step2,step3...).
So, in order to achieve that, I am using Template design pattern.
Please review and suggest if I am implementing this problem correctly, or there is a better solution.
I am suspecting my approach will introduce code smells, as I am changing values of objects very frequently.
Also, suggest if I & how can I use Java 8 to accomplish this?
Thanks.
Code:
package com.example.demo.design;
import java.util.List;
public abstract class Template {
#Autowired
private Step1 step1;
#Autowired
private Step2 step2;
#Autowired
private Save save;
List<String> stepOutput = null;
List<String> stepOutputTwo = null;
List<String> stepOutputThree = null;
public void step1(String action1) {
stepOutput = step1.method(action1);
}
public void step2(String action2) {
stepOutputTwo = step2.method(stepOutput, action2);
}
abstract public void step3();
public void save() {
save.persist(stepOutputThree);
}
final public void run(String action1, String action2) {
step1(action1);
step2(action2);
stepOutputTwo = step3();
}
}
In Java 8 streams model, that could look like the following:
final public void run(String action1, String action2) {
Stream.of(action1) // Stream<String>
.map(s -> step1.method(s)) // Stream<List<String>>
.map(l -> step2.method(l,action2) // Stream<List<String>>
.map(l -> step3.method(l)) // Stream<List<String>>
.forEach(l -> save.persist(l));
}
I had same issue! you can do something like this: and uncheckCall method is for handling exceptions.
final public void run(String action1, String action2) {
//other stuffs
Stream.of(step1.method(action1))
.map(stepOutput->uncheckCall(() ->step2.method(stepOutput,action2)))
.forEach(stepOutputThree -> uncheckCall(()->save.persist(stepOutputThree)));
//.....
}
for uncheckCall method:
public static <T> T uncheckCall(Callable<T> callable) {
try {
return callable.call();
} catch (RuntimeException e) {
// throw BusinessException.wrap(e);
} catch (Exception e) {
//throw BusinessException.wrap(e);
}
}
Well, when there are "pipelines", "sequence of operations", etc. the first design pattern that comes to mind is Chain of Responsibility, that looks like the following
and provides you with these benefits:
allows you to add new handlers when necessary (e.g. at runtime) without modifying other handlers and processing logic (Open/Closed Principle of SOLID)
allows a handler to stop processing a request if necessary
allows you to decouple processing logic of the handlers from each other (Single Responsibility Principle of SOLID)
allows you to define the order of the handlers to process a request outside of the handlers themselves
One example of real world usage is Servlet filters where you call doFilter(HttpRequest, HttpResponse, FilterChain) to invoke the next handler
protected void doFilter(HttpServletRequest req, HttpServletResponse resp, FilterChain chain) {
if (haveToInvokeNextHandler) {
chain.doFilter(req, resp);
}
}
In case of using classical Chain of Responsibility pattern your processing pipeline may look like the following:
API
public class StepContext {
private Map<String, Object> attributes = new HashMap<>();
public <T> T getAttribute(String name) {
(T) attributes.get(name);
}
public void setAttribute(String name, Object value) {
attributes.put(name, value);
}
}
public interface Step {
void handle(StepContext ctx);
}
public abstract class AbstractStep implements Step {
private Step next;
public AbstractStep() {
}
public AbstractStep(Step next) {
this.next = next;
}
protected void next(StepContext ctx) {
if (next != null) {
next.handle(ctx);
}
}
}
Implementation
public class Step1 extends AbstractStep {
public Step1(Step next) {
super(next);
}
public void handle(StepContext ctx) {
String action1 = ctx.getAttribute("action1");
List<String> output1 = doSomething(action1);
ctx.setAttribute("output1", output1);
next(ctx); // invoke next step
}
}
public class Step2 extends AbstractStep {
public Step2(Step next) {
super(next);
}
public void handle(StepContext ctx) {
String action2 = ctx.getAttribute("action2");
List<String> output1 = ctx.getAttribute("output1");
List<String> output2 = doSomething(output1, action2);
ctx.setAttribute("output2", output2);
next(ctx); // invoke next step
}
}
public class Step3 extends AbstractStep {
public Step3(Step next) {
super(next);
}
public void handle(StepContext ctx) {
String action2 = ctx.getAttribute("action2");
List<String> output2 = ctx.getAttribute("output2");
persist(output2);
next(ctx); // invoke next step
}
}
Client code
Step step3 = new Step3(null);
Step step2 = new Step2(step3);
Step step1 = new Step1(step2);
StepContext ctx = new StepContext();
ctx.setAttribute("action1", action1);
ctx.setAttribute("action2", action2);
step1.handle(ctx);
Also all this stuff can be simplified into a chain of handlers decoupled from each other by means of removing the corresponding next references in case your processing pipeline will have to always invoke all the available steps without controlling the necessity of invocation from the previous one:
API
public class StepContext {
private Map<String, Object> attributes = new HashMap<>();
public <T> T getAttribute(String name) {
(T) attributes.get(name);
}
public void setAttribute(String name, Object value) {
attributes.put(name, value);
}
}
public interface Step {
void handle(StepContext ctx);
}
Implementation
public class Step1 implements Step {
public void handle(StepContext ctx) {
String action1 = ctx.getAttribute("action1");
List<String> output1 = doSomething(action1);
ctx.setAttribute("output1", output1);
}
}
public class Step2 implements Step {
public void handle(StepContext ctx) {
String action2 = ctx.getAttribute("action2");
List<String> output1 = ctx.getAttribute("output1");
List<String> output2 = doSomething(output1, action2);
ctx.setAttribute("output2", output2);
}
}
public class Step3 implements Step {
public void handle(StepContext ctx) {
String action2 = ctx.getAttribute("action2");
List<String> output2 = ctx.getAttribute("output2");
persist(output2);
}
}
Client code
Note that in case of Spring framework (just noticed #Autowired annotation) the client code may be simplified even more as the #Autowired annotation can be used to inject all the beans of the corresponding type into a corresponding collection.
Here what the documentation states:
Autowiring Arrays, Collections, and Maps
In case of an array, Collection, or Map dependency type, the container autowires all beans matching the declared value type. For such purposes, the map keys must be declared as type String which will be resolved to the corresponding bean names. Such a container-provided collection will be ordered, taking into account Ordered and #Order values of the target components, otherwise following their registration order in the container. Alternatively, a single matching target bean may also be a generally typed Collection or Map itself, getting injected as such.
public class StepsInvoker {
// spring will put all the steps into this collection in order they were declared
// within the spring context (or by means of `#Order` annotation)
#Autowired
private List<Step> steps;
public void invoke(String action1, String action2) {
StepContext ctx = new StepContext();
ctx.setAttribute("action1", action1);
ctx.setAttribute("action2", action2);
steps.forEach(step -> step.handle(ctx))
}
}

Spring Batch - Using an ItemWriter with List of Lists

Our processor returns a List<?> (effectively passing a List<List<?>>) to our ItemWriter.
Now, we observed that the JdbcBatchItemWriter is not programmed to handle item instanceof List. We also observed to process item instanceof List; we need to write a custom ItemSqlParameterSourceProvider.
But the sad part is that it returns SqlParameterSource which can handle only one item and again not capable of handling a List.
So, can someone help us understand how to handle list of lists in the JdbcBatchItemWriter?
Typically, the design pattern is:
Reader -> reads something, returns ReadItem
Processor -> ingests ReadItem, returns ProcessedItem
Writer -> ingests List<ProcessedItem>
If your processor is returning List<Object>, then you need your Writer to expect List<List<Object>>.
You could do this by wrapping your JdbcBatchItemWriter as a delegate in an ItemWriter that looks something like this:
public class ListUnpackingItemWriter<T> implements ItemWriter<List<T>>, ItemStream, InitializingBean {
private ItemWriter<T> delegate;
#Override
public void write(final List<? extends List<T>> lists) throws Exception {
final List<T> consolidatedList = new ArrayList<>();
for (final List<T> list : lists) {
consolidatedList.addAll(list);
}
delegate.write(consolidatedList);
}
#Override
public void afterPropertiesSet() {
Assert.notNull(delegate, "You must set a delegate!");
}
#Override
public void open(ExecutionContext executionContext) {
if (delegate instanceof ItemStream) {
((ItemStream) delegate).open(executionContext);
}
}
#Override
public void update(ExecutionContext executionContext) {
if (delegate instanceof ItemStream) {
((ItemStream) delegate).update(executionContext);
}
}
#Override
public void close() {
if (delegate instanceof ItemStream) {
((ItemStream) delegate).close();
}
}
public void setDelegate(ItemWriter<T> delegate) {
this.delegate = delegate;
}
}
public class ListUnpackingItemWriter<T> implements FlatFileItemWriter<List<T>>, ItemStream, InitializingBean {
#Override
public void afterPropertiesSet() {
setLineAggregator(item -> String.join("\n", item.stream().map(T::toString).collect(Collectors.toList())));
}
}
Just added a custom line aggregator to the above solution, this helps in writing the content to a file by using FlatFileItemWriter<List<T>>. You can replace T with actual class name to avoid compilation error while calling toString() method.

Use of Generics during validation

I am using apache CXF.
The following API is used to post a Contact.
#POST
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
ResponseResult create(#Context HttpHeaders httpHeaders, #Context Request request, #Context UriInfo uriInfo,
UserContact contact) throws MDMException;
Here the UserContact class contains the contact information about a user which is passed as JSON in the body.
I need to do some business validations on this UserContact object. But I do not like to have too much validation code packed in a single class.
I would like to do something like the following. But I am facing issue with Generics.
interface Rule<S>
{
void applyRule(S s)throws Exception;
}
interface Validatable
{
void validate() throws Exception;
}
public class MyValidator
{
private HashMap<? extends Rule ,?> map = new HashMap<>();
public void validate() throws Exception
{
for(Rule rule : map.keySet())
{
rule.applyRule(map.get(rule));
}
}
public <S> void addRule(Rule<S> rule, S data)
{
this.map.put(rule, data);
}
}
class EMailValidationRule implements Rule<String>
{
private static final Pattern emailPattern = Pattern.compile("email-regex");
public void applyRule(String s) throws Exception
{
if(!emailPattern.matcher(s).matches())
throw new Exception("Not a valid EMail");
}
}
So the UserContact has to do the following for its validation purposes. This keeps the code compact (IMO).
class UserContact implements Validatable
{
// some
// code
// related to User Contact
public void validate() throws Exception
{
MyValidator validator = new MyValidator();
validator.addRule(new EMailValidationRule(), "developer#stackoverflow.com");
validator.addRule(new PhoneValidationRule(), "+1234567890");
validator.validate();
}
}
I keep getting error like :
The method put(capture#5-of ? extends Rule, capture#6-of ?) in the type HashMap is not applicable
for the arguments (Rule, S)
Also is the above design good for doing validations?
The problem is that, although your encapsulation ensures it, the compiler can not be sure that the retrieved Rule<...> has a type argument of the same type as the retrieved data.
There is also the problem of not being able to insert a Rule<T> with data of a subtype of T. If you have Rule<S> rule, S data the types have to be an exact match. While a Rule<S> could handle a subtype of S just fine.
While MyValidator is a cool little class, I can't really see the point in having it. Especially because you create a new one every time you call validate. It would also be hard to cache because the rules are static (the same for every instance of the class) and the data comes from individual instances (I'd assume).
You could also just do this:
class UserContact implements Validatable
{
// some
// code
// related to User Contact
// 1 rule instance for the entire class, not a new one per call to 'validate'
private static EMailValidationRule emailRule = new EmailValidationRule();
private static PhoneValidationRule phoneRule = new PhoneValidationRule();
public void validate() throws Exception
{
emailRule.applyRule("developer#stackoverflow.com");
phoneRule.applyRule("+1234567890");
}
}
Never the less, here is a working version of MyValidator:
class MyValidator {
private Map<Rule<?>, RuleNode<?>> map = new HashMap<>();
public void validate() throws Exception {
for(RuleNode<?> node : map.values())
node.apply();
}
public <T, D extends T> void addRule(Rule<T> rule, D data) {
#SuppressWarnings("unchecked") // unchecked, but safe due to encapsulation
RuleNode<T> r = (RuleNode<T>) map.get(rule);
if(r == null) {
r = new RuleNode<T>(rule);
map.put(rule, r);
}
r.add(data);
}
private static class RuleNode<T> { // Maintains that the rule and data are compatible
private final Rule<T> rule;
private final List<T> list = new ArrayList<>();
public RuleNode(Rule<T> rule) {
this.rule = rule;
}
public void add(T data) {
list.add(data);
}
public void apply() throws Exception {
for(T data : list)
rule.applyRule(data);
}
}
}
You just need to make a generic Version of the MyValidator Class
A generic class is defined with thss format:
class name<T1, T2, ..., Tn> { /* ... */ }
Defining the class using generics you will specify the types you want to use in your class, in your case <R extends Rule<S> ,S>
class MyValidator<R extends Rule<S> ,S>{
private HashMap<R ,S> map = new HashMap<>();
public void validate() throws Exception{
for(Rule<S> rule : map.keySet()){
rule.applyRule(map.get(rule));
}
}
public void addRule(R rule, S data){
this.map.put(rule, data);
}
}
Once done you just have to build a MyValidator of the desired type :
MyValidator<Rule<String>, String> validator = new MyValidator<>();
And finally add the rules matching the types of the validator :
validator.addRule(new EMailValidationRule(), "developer#stackoverflow.com");
So for example addind a phone validator your UserContact will looks like :
class PhoneValidationRule implements Rule<String>{
private static final Pattern phonePattern = Pattern.compile("phone-regex");
public void applyRule(String s) throws Exception{
if(!phonePattern.matcher(s).matches())
throw new Exception("Not a valid phone");
}
}
class UserContact implements Validatable{
public void validate() throws Exception{
MyValidator<Rule<String>, String> validator = new MyValidator<>();
validator.addRule(new EMailValidationRule(), "developer#stackoverflow.com");
validator.addRule(new PhoneValidationRule(), "developer#stackoverflow.com");
validator.validate();
}
}

Java Observers/Object Listeners (Game Engine)

I'm working on a game engine, and the last question I had regarding this was what good way I can use to make "observers" or listeners. A user suggested that I should use Java's EventObject class to inherit from and make a Listener interface. However, this didn't provide me with good flexibility.
Here is the Handler annotation to state that a method is an event handler in a listener:
#Retention(RetentionPolicy.CLASS)
#Target(ElementType.METHOD)
public #interface Handler {}
Here is the base class for Event, which is basically the same as EventObject (but I'll add abstract methods sooner or later):
public abstract class Event {
private Object source;
public Event(Object source) {
this.source = source;
}
public Object getSource() {
return source;
}
}
Here is the Listener class, which is empty:
public interface Listener {}
Here is the ListenerHandler class, used to handle all listeners. You register and unregister them here. I'll edit the register/unregister methods later for a better use:
public class ListenerHandler {
private ArrayList<Listener> listeners;
public ListenerHandler() {
this.listeners = new ArrayList<Listener>();
}
public void registerListener(Listener l) {
listeners.add(l);
}
public void unregisterListener(Listener l) {
listeners.remove(l);
}
public void onEvent(Event event) {
for(Listener l : listeners) {
Class<?> c = l.getClass();
Method[] methods = c.getDeclaredMethods();
for(Method m : methods) {
if(m.isAccessible()) {
if(m.isAnnotationPresent(Handler.class)) {
Class<?>[] params = m.getParameterTypes();
if(params.length > 1) {
continue;
}
Class<?> par = params[0];
if(par.getSuperclass().equals(Event.class)) {
try {
m.invoke(this, event);
}catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
}
}
}
From what I heard, it's a use of a lot of memory in order to get all methods of a class. I'm not going to assume this is the case, but I'm sure there is a better way as this will be a game engine with many components and such.
I'd like to know the best way to implement this, or if I'm doing it right. I'd also like to know if anyone can help me improve this in any way without hogging memory usage by the game (as of now it's not a big deal -- the "game engine" is not even close to rendering anything yet)
I tried to keep it a very simple example and will comment with different ideas to it:
First meet the Achievement class:
import java.util.Observable;
public class Achievement extends Observable {
public static class AchievementDetails {}
public Achievement() {
addObserver(EventsListener.getInstance());
}
public void achievementReached() {
AchievementDetails achievemetDetails = null;
setChanged();
notifyObservers(achievemetDetails);
}
}
And then the events listener class:
import com.test.Achievement.AchievementDetails;
public class EventsListener implements Observer {
private static EventsListener instance = new EventsListener();
public static EventsListener getInstance() {
return instance;
}
#Override
public void update(Observable o, Object arg) {
if(o instanceof Achievement) {
AchievementDetails achievemetDetails = (AchievementDetails) arg;
//do some logic here
}
}
}
The only one thing that is missing is to create an instance of your achievement (which register the EventsListener to itself) and handle the life cycle of it.

Handling Runtime dependencies

Dependency injection is a useful technique but what approach is recommended when faced with runtime dependencies?
e.g. Say you want to glue an event to an event processor depending on the type of the event and the user who initiated the request.
public interface Event {}
public interface EventProcessor {
public void handleEvent(Event e);
}
class EventProcessorFactory {
private final User u;
private final Event e;
public EventProcessorFactory(User u, Event e) {
this.u = u;
this.e = e;
}
public EventProcessor get() {
EventProcessor ep;
if(e instanceof LocalEvent) {
ep = new LocalEventProcessor();
}
else if(e instanceof RemoteTriggeredEvent && u instanceof AdminUser) {
//has static dependencies
ep = new RemoteEventProcessor(u);
}
else {
ep = new DefaultEventProcessor();
}
}
}
Now the complexity is encapsulated in the factory, but how else could I achieve the same result, without too much boilerplate code?
As written, what you call 'boilerplate code' looks to me to be just 'code'. You have some processing logic that needs to be stated somewhere (local events go to a local event processor, etc). Trying to avoid explicitly stating that logic could be a mistake.
If it is what you do want to do, the simplest way of doing it is to change the interface to add a method:
boolean isInterestedInEvent(Event e)
then set up all the event processors and loop over them until you find the right one.
You could use something like
public interface EventProcessor {
public boolean supports(Event event, User user);
public void handleEvent(Event event);
}
class EventProcessorFactory {
public void setEventProcessors(List<EventProcessor> processors) {
this.processors = processors;
}
public EventProcessor get(Event event, User user) {
for (EventProcessor processor : processors) {
if (processor.supports(event, user)
return processor;
}
}
}
class LocalEventProcessor implements EventProcessor {
public boolean supports(Event event, User user) {
return (event instanceof LocalEvent);
}
// etc
}
class RemoteEventProcessor implements EventProcessor {
public boolean supports(Event event, User user) {
return (event instanceof RemoteTriggeredEvent) &&
(user instanceof AdminUser);
}
// etc
}
If your processors have some sort of natural ordering, you can implement Comparable to ensure they are tested in the correct order, otherwise you'll can rely on them being injected into the factory in the required order, thus making it configurable.
You could make each Event responsible for creating the EventProcessor. That way you reduce the number of instanceof checks you're required to make and also achieve better encapsulation. Despite being more "OO" the trade-off is that the logic is no longer in one place (i.e. sometimes it's better to just stick with a "procedural approach" as per your example).
public interface Event {
EventProcessor createProcessor(User u);
}
public class RemoteTriggeredEvent implements Event {
public EventProcessor createProcessor(User u) {
return (u instanceof AdminUser) ? new RemoteEventProcessor(u) :
new DefaultEventProcessor();
}
}

Categories