Following is my code isolation.
Interactable Interface.
public interface Interactable <E extends Interactable> {
List<Person> personsInteracting = new ArrayList<>();
List<Person> personsWaiting = new ArrayList<>();
long INTERACTION_TIME = 5 * 60;
default int getNumberOfPeopleInteracting () {
return personsInteracting.size();
}
default int getNumberOfPeopleWaiting () {
return personsWaiting.size();
}
boolean isMultipleActionsAllowed ();
boolean isFurtherActionsAllowed ();
public abstract boolean tryOccupiedBy (final Person person, final Interactions interaction)
throws InteractionNotPossibleException;
E getObject ();
EnumSet<Interactions> getInteractions ();
}
InteractiveObject Abstract Class
public abstract class InteractiveObject implements Interactable {
protected final String name;
protected int numberOfSimultaneousInteractions;
protected Interactions currentInteraction;
public InteractiveObject (final String name) {
this.name = name;
}
#Override
public boolean isMultipleActionsAllowed () {
return numberOfSimultaneousInteractions > 1;
}
#Override
public boolean isFurtherActionsAllowed () {
return personsInteracting.isEmpty() ||
(getNumberOfPeopleInteracting() > numberOfSimultaneousInteractions);
}
#Override
public boolean tryOccupiedBy (final Person person, final Interactions interaction)
throws InteractionNotPossibleException {
boolean isOccupied = false;
if (!isFurtherActionsAllowed()) {
throw new InteractionNotPossibleException(this + " is already in use by some other " +
"person.");
}
personsInteracting.add(person);
currentInteraction = interaction;
return isOccupied;
}
#Override
public String toString () {
return name;
}
public int getNumberOfSimultaneousInteractions () {
return numberOfSimultaneousInteractions;
}
}
Chair (One of the child class)
public class Chair extends InteractiveObject {
private final EnumSet<Interactions> INTERACTIONS = EnumSet.copyOf(Arrays.asList(
new Interactions[] {Interactions.DRAG, Interactions.SIT}));
public Chair (final String objectName) {
super(objectName);
super.numberOfSimultaneousInteractions = 1;
}
#Override
public Interactable getObject () {
return this;
}
#Override
public EnumSet<Interactions> getInteractions () {
return INTERACTIONS;
}
}
Here is the piece of code that executes and brings the problem, this question is asked for.
final InteractiveObject chair1 = new Chair("Chair1");
final Person person1 = new Person("Person1");
final Room room = new Room("Room1", 2, 2);
room.personEnters(person1);
room.putObject(chair1);
person1.tryOccupying(chair1);
Above piece of code, successfully occupies the chair object. Now,
final InteractiveObject chair2 = new Chair("Chair2");
final Person person2 = new Person("Person2");
final Room room2 = new Room("Room2", 2, 2);
room2.personEnters(person2);
room2.putObject(chair2);
person2.tryOccupying(chair2);
This piece of code doesn't let the person2 occupy since my code states that 1 person is already interacting with chair2, where as no one is interacting with it.
Solution of my problem:
I moved my List of personInteracting to InteractiveObject and function tryOccupiedBy to each child class and everything works fine.
Questions:
I put personsInteracting in Interactable interface since I believe that every future implementation of Interactable will have it. Developers won't have to implement themselves. (But perhaps this idea seems to be wrong)
If tryOccupiedBy function has same implementation, what is the purpose of whole OOP?
I now know that the isolation was wrong and I know where to place the pieces to get the results. But can someone kindly point me out about some OOP concept which I did not understand and should be implemented in a much better way?
The default keyword was not added to the Java language to do the kind of thing which you seem to be trying to achieve. Data defined in an interface is intended to be constant - the modifiers 'public static' are automatically applied to any field definitions in an interface. If you create a default method in the interface then it must either be stateless or act directly only on purely statically available state. Default methods can call other interface methods to modify instance state, .
By placing personsInteracting field in the interface, you made the same instance common to every object implementing that interface, and so your tryOccupying method was acting on purely global state.
So, the purpose of having default methods in the Java language is to support adding new methods to interfaces in a backwards compatible fashion, nothing more. You shouldn't reuse it as a generic form of code re-use - it was never intended for that and you'll get (as you did) weird behaviour.
You didn't have to put tryOccupiedBy in the child classes, however, so you didn't have to have a load of duplicated code. You could still declare the method signature in the interface (which is what interfaces are generally supposed to do) and then implement the common method in your abstract base class. By putting the data fields in the base class, you make them instance fields and so they are not shared between objects.
public interface Interactable <E extends Interactable> {
...
boolean tryOccupiedBy (final Person person, final Interactions interaction)
throws InteractionNotPossibleException;
...
}
public abstract class InteractiveObject implements Interactable {
private final List<Person> personsInteracting = new ArrayList<>();
private final List<Person> personsWaiting = new ArrayList<>();
...
#Override
public final boolean tryOccupiedBy (final Person person, final Interactions interaction)
throws InteractionNotPossibleException {
boolean isOccupied = false;
if (!isFurtherActionsAllowed()) {
throw new InteractionNotPossibleException(this + " is already in use by some other " +
"person.");
}
personsInteracting.add(person);
currentInteraction = interaction;
return isOccupied;
}
...
}
Related
In my project, I have this special function that does needs to evaluate the following:
State -- represented by an enum -- and there are about 6 different states
Left Argument
Right Argument
Left and Right arguments are represented by strings, but their values can be the following:
"_" (a wildcard)
"1" (an integer string)
"abc" (a normal string)
So as you can see, to cover all every single possibility, there's about 2 * 3 * 6 = 36 different logics to evaluate and of course, using if-else in one giant function will not be feasible at all. I have encapsulated the above 3 input into an object that I'll pass to my function.
How would one try to use OOP to solve this. Would it make sense to have 6 different subclasses of the main State class with an evaluate() method, and then in their respective methods, I have if else statements to check:
if left & right arg are wildcards, do something
if left is number, right is string, do something else
Repeat for all the valid combinations in each State subclass
This feels like the right direction, but it also feels like theres alot of duplicate logic (for example check if both args are wildcards, or both strings etc.) for all 6 subclasses. Then my thought is to abstract it abit more and make another subclass:
For each state subclass, I have stateWithTwoWildCards, statewithTwoString etc.
But I feel like this is going way overboard and over-engineering and being "too" specific (I get that this technically adheres tightly to SOLID, especially SRP and OCP concepts). Any thoughts on this?
Possibly something like template method pattern can be useful in this case. I.e. you will encapsulate all the checking logic in the base State.evaluate method and create several methods which subclasses will override. Something along this lines:
class StateBase
def evaluate():
if(bothWildcards)
evalBothWildcards()
else if(bothStrings)
evalBothStrings()
else if ...
def evalBothWildcards():
...
def evalBothStrings():
...
Where evalBothWildcards, evalBothStrings, etc. will be overloaded in inheritors.
there's about 2 * 3 * 6 = 36 different logics to evaluate
We can apply divide and conquer technique.
you have 6 states. It is possible to use Chain of Responibility pattern here to choose appropriate state handler
when desired state handler is found, then we can apply desired function. The appropriate function can be considered as strategy. So it is a place where Strategy pattern can be applied.
we can separate strategies by appropriate states and put them in simple factory to get desired strategy by key.
This is what we will do. So let's see it more thoroughly.
Chain of responsibility pattern
If you have a lot if else statements, it is possible to use Chain of Responsibility pattern. As wiki says about Chain of Responsibility:
The chain-of-responsibility pattern is a behavioral design pattern
consisting of a source of command objects and a series of processing
objects. Each processing object contains logic that defines the
types of command objects that it can handle; the rest are passed to
the next processing object in the chain. A mechanism also exists for
adding new processing objects to the end of this chain
So let's dive in code. Let me show an example via C#.
So this is our Argument class which has Left and Right operands:
public class Arguments
{
public string Left { get; private set; }
public string Right { get; private set; }
public MyState MyState { get; private set; }
public MyKey MyKey => new MyKey(MyState, Left);
public Arguments(string left, string right, MyState myState)
{
Left = left;
Right = right;
MyState = myState;
}
}
And this is your 6 states:
public enum MyState
{
One, Two, Three, Four, Five, Six
}
This is start of Decorator pattern. This is an abstraction of StateHandler which defines behaviour to to set next handler:
public abstract class StateHandler
{
public abstract MyState State { get; }
private StateHandler _nextStateHandler;
public void SetSuccessor(StateHandler nextStateHandler)
{
_nextStateHandler = nextStateHandler;
}
public virtual IDifferentLogicStrategy Execute(Arguments arguments)
{
if (_nextStateHandler != null)
return _nextStateHandler.Execute(arguments);
return null;
}
}
and its concrete implementations of StateHandler:
public class OneStateHandler : StateHandler
{
public override MyState State => MyState.One;
public override IDifferentLogicStrategy Execute(Arguments arguments)
{
if (arguments.MyState == State)
return new StrategyStateFactory().GetInstanceByMyKey(arguments.MyKey);
return base.Execute(arguments);
}
}
public class TwoStateHandler : StateHandler
{
public override MyState State => MyState.Two;
public override IDifferentLogicStrategy Execute(Arguments arguments)
{
if (arguments.MyState == State)
return new StrategyStateFactory().GetInstanceByMyKey(arguments.MyKey);
return base.Execute(arguments);
}
}
and the third state handler looks like this:
public class ThreeStateHandler : StateHandler
{
public override MyState State => MyState.Three;
public override IDifferentLogicStrategy Execute(Arguments arguments)
{
if (arguments.MyState == State)
return new StrategyStateFactory().GetInstanceByMyKey(arguments.MyKey);
return base.Execute(arguments);
}
}
Strategy pattern
Let's pay attention to the following row of code:
return new StrategyStateFactory().GetInstanceByMyKey(arguments.MyKey);
The above code is an example of using Strategy pattern. We have different ways or strategies to handle
your cases. Let me show a code of strategies of evaluation of your expressions.
This is an abstraction of strategy:
public interface IDifferentLogicStrategy
{
string Evaluate(Arguments arguments);
}
And its concrete implementations:
public class StrategyWildCardStateOne : IDifferentLogicStrategy
{
public string Evaluate(Arguments arguments)
{
// your logic here to evaluate "_" (a wildcard)
return "StrategyWildCardStateOne";
}
}
public class StrategyIntegerStringStateOne : IDifferentLogicStrategy
{
public string Evaluate(Arguments arguments)
{
// your logic here to evaluate "1" (an integer string)
return "StrategyIntegerStringStateOne";
}
}
And the third strategy:
public class StrategyNormalStringStateOne : IDifferentLogicStrategy
{
public string Evaluate(Arguments arguments)
{
// your logic here to evaluate "abc" (a normal string)
return "StrategyNormalStringStateOne";
}
}
Simple factory
There is no pattern like simple factory. However, it is a place where we can get instances of strategies by key. So by doing this we avoided to use multiple if else statements to choose correct strategy.
So, we need a place where we can store strategies by state and argument value. At first, let's create MyKey struct. It will have help us to differentiate State and arguments:
public struct MyKey
{
public readonly MyState MyState { get; }
public readonly string ArgumentValue { get; } // your three cases: "_",
// an integer string, a normal string
public MyKey(MyState myState, string argumentValue)
{
MyState = myState;
ArgumentValue = argumentValue;
}
public override bool Equals([NotNullWhen(true)] object? obj)
{
return obj is MyKey mys
&& mys.MyState == MyState
&& mys.ArgumentValue == ArgumentValue;
}
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
hash = hash * 23 + MyState.GetHashCode();
hash = hash * 23 + ArgumentValue.GetHashCode();
return hash;
}
}
}
and then we can create a simple factory:
public class StrategyStateFactory
{
private Dictionary<MyKey, IDifferentLogicStrategy>
_differentLogicStrategyByStateAndValue =
new Dictionary<MyKey, IDifferentLogicStrategy>()
{
{ new MyKey(MyState.One, "_"), new StrategyWildCardStateOne() },
{ new MyKey(MyState.One, "intString"),
new StrategyIntegerStringStateOne() },
{ new MyKey(MyState.One, "normalString"),
new StrategyNormalStringStateOne() }
};
public IDifferentLogicStrategy GetInstanceByMyKey(MyKey myKey)
{
return _differentLogicStrategyByStateAndValue[myKey];
}
}
So we've written our strategies and we've stored these strategies in simple factory StrategyStateFactory.
Then we need to check the above implementation:
StateHandler chain = new OneStateHandler();
StateHandler secondStateHandler = new TwoStateHandler();
StateHandler thirdStateHandler = new ThreeStateHandler();
chain.SetSuccessor(secondStateHandler);
secondStateHandler.SetSuccessor(thirdStateHandler);
Arguments arguments = new Arguments("_", "_", MyState.One);
IDifferentLogicStrategy differentLogicStrategy = chain.Execute(arguments);
string evaluatedResult =
differentLogicStrategy.Evaluate(arguments); // output: "StrategyWildCardStateOne"
I believe I gave basic idea how it can be done.
When using toList() ConstraintCollector in optaplanner 8.1 like:
factory.from(Lesson.class)
.groupBy(Lesson::getCourse, ConstraintCollectors.toList()).penalize(...);
I run into:
Exception executing consequence for rule "foo" in model: java.lang.ClassCastException: class model.Lesson cannot be cast to class java.util.List (model.Lesson is in unnamed module of loader 'app'; java.util.List is in module java.base of loader 'bootstrap')
at org.drools.core.runtime.rule.impl.DefaultConsequenceExceptionHandler.handleException(DefaultConsequenceExceptionHandler.java:39)
Question: Is this a optaplanner bug, or is my code wrong?
The most simple complete reproducer I find is:
#PlanningSolution
public class OptaplannerIssue2 implements ConstraintProvider {
#Override
public Constraint[] defineConstraints(ConstraintFactory factory) {
return new Constraint[] {factory.from(IssueEntity.class)
.groupBy(IssueEntity::getValue, ConstraintCollectors.toList())
.penalize("x", HardSoftScore.ofHard(1), (entity, enityList) -> 2)};
}
#PlanningScore
private HardSoftScore score = HardSoftScore.ZERO;
#PlanningEntityCollectionProperty
private final List<IssueEntity> entities = new ArrayList<IssueEntity>();
public List<IssueEntity> getEntities() {
return entities;
}
#ValueRangeProvider(id = "valueRange")
public CountableValueRange<Integer> getValueRange() {
return ValueRangeFactory.createIntValueRange(0, 4);
}
public static void main() {
// create Entity
OptaplannerIssue2 issue = new OptaplannerIssue2();
IssueEntity e1 = new IssueEntity();
issue.entities.add(e1);
// solve
SolverFactory<OptaplannerIssue2> solverFactory = SolverFactory.create(new SolverConfig()
.withEnvironmentMode(EnvironmentMode.FULL_ASSERT).withSolutionClass(OptaplannerIssue2.class)
.withEntityClasses(IssueEntity.class)
.withScoreDirectorFactory(
new ScoreDirectorFactoryConfig().withConstraintProviderClass(OptaplannerIssue2.class))
.withTerminationConfig(new TerminationConfig().withSecondsSpentLimit(5L)).withPhases(
new ConstructionHeuristicPhaseConfig()
.withConstructionHeuristicType(ConstructionHeuristicType.FIRST_FIT),
new LocalSearchPhaseConfig().withLocalSearchType(LocalSearchType.LATE_ACCEPTANCE)));
Solver<OptaplannerIssue2> solver = solverFactory.buildSolver();
solver.solve(issue);
}
}
With the following entity-class:
#PlanningEntity
public class IssueEntity {
#PlanningVariable(valueRangeProviderRefs = {"valueRange"})
Integer value;
public Integer getValue() {
return value;
}
}
In the related thread: Optaplanner GroupBy with toList not working as expected the questioner didn't provide all information to commentators trying to help and when I provided reproducer there I got deleted, so I had to ask new question.
The behavior you describe is a bug in OptaPlanner, which we have now fixed. Please upgrade to the next release of OptaPlanner, which at the time of writing this answer will be OptaPlanner 8.2.0.
For details, see PLANNER-2305.
Let's assume we have a simple payment feature on an online shop. We want to manage different transactions with different processors of transactions:
A transaction can be a payment or a refund.
A processor of transactions can be Paypal or Payplug.
So we have the following classes:
class PaymentTransaction implements Transaction {
}
class RefundTransaction implements Transaction {
}
class PaypalProcessor implements Processor {
}
class PayplugProcessor implements Processor {
}
As suggested in this answer, we could use the following class which uses Strategy and polymorphism.
class PaymentProcessor {
private Processor processor;
private Transaction transaction;
public PaymentProcessor(Processor processor, Transaction transaction) {
this.processor = processor;
this.transaction = transaction;
}
public void processPayment() {
processor.process(transaction);
}
}
We assume the processor and the transaction to use are given from the database. I wonder how to create the PaymentProcessor object.
It seems that an abstract factory class with only one method is still a valid Abstract Factory pattern. So, in this case I wonder if using Abstract Factory would be relevant.
If yes, how to implement it?
If no, should we use Factory Method pattern with a PaymentProcessorFactory class to create PaymentProcessor with his two attributes according the details given from the database?
What is a best practice to use a factory in this case?
We assume the processor and the transaction to use are given from the database. I wonder how to create the PaymentProcessor object.
I would define an interface that I can adapt to the database result or any other source that can provide the data needed to create a PaymentProcessor. This is also useful for unittests.
public interface PaymentProcessorFactoryArgs {
String getProcessorType();
String getTransactionType();
}
and then implement a factory like this.
public class PaymentProcessorFactory {
private Map<String, Processor> processorMap = new HashMap<>();
private Map<String, Transaction> transactionMap = new HashMap<>();
public PaymentProcessorFactory() {
processorMap.put("paypal", new PaypalProcessor());
processorMap.put("payplug", new PayplugProcessor());
transactionMap.put("refund", new RefundTransaction());
transactionMap.put("payment", new PaymentTransaction());
}
public PaymentProcessor create(PaymentProcessorFactoryArgs factoryArgs) {
String processorType = factoryArgs.getProcessorType();
Processor processor = processorMap.get(processorType);
if(processor == null){
throw new IllegalArgumentException("Unknown processor type " + processorType);
}
String transactionType = factoryArgs.getTransactionType();
Transaction transaction = transactionMap.get(transactionType);
if(transaction == null){
throw new IllegalArgumentException("Unknown transaction type " + processorType);
}
return new PaymentProcessor(processor, transaction);
}
}
This is just a quick example. It would be better if you can register Processors and Transactions. E.g.
public void register(String processorType, Processor processor){
...
}
public void register(String transactionType, Transaction transaction){
...
}
You also might want to use anther type then String for the keys, maybe an enum.
In this example the Processor and Transaction objects are re-used every time a PaymentProcessor is created. If you want to create new objects for each PaymentProcessor, you can replace the Maps type
private Map<String, Factory<Processor>> processorMap = new HashMap<>();
private Map<String, Factory<Transaction>> transactionMap = new HashMap<>();
with anther factory interface. E.g.
public interface Factory<T> {
public T newInstance();
}
Maybe you can use the builder pattern. In the builder pattern there is a class called the director, which knows the algorithm of creating a complex object. To create the components the complex object is build of the director uses a builder. Like this you can change specific components to build up the whole complex object.
In your case the PaymentProcessor (the complex object) is composed out of a Payment and a Processor, so the algorithm is to inject them into a PaymentProcessor. The builder should build the parts. To build a paypal-refund combination you should create a builder which returns a PaypalProcessor and a RefundTransaction. When you want to create a payplug-payment the builder should return a PaymentTransaction and a PayPlugProcessor.
public interface PaymentProcessorBuilder {
public Transaction buildTransaction();
public Processor buildProcessor();
}
public class PaypalRefundProcessorBuilder implements PaymentProcessorBuilder {
public Transaction buildTransaction {
return new RefundTransaction();
}
public Processor buildProcessor {
return new PayPalProcessor();
}
}
public class PayPlugPaymentProcessorBuilder implements PaymentProcessorBuilder {
public Transaction buildTransaction {
return PaymentTransaction();
}
public Processor buildProcessor {
return new PayPlugProcessor();
}
}
Now the Director can use the builder to compose the PaymentProcessor:
publi PaymentProcessorDirector {
public PaymentProcessor createPaymentProcessor(PaymentProcessorBuilder builder) {
PaymentProcessor paymentProcessor = new PaymentProcessor();
paymentProcessor.setTransaction(builder.buildTransaction());
paymentProcessor.setProcessor(builder.buildProcessor());
return paymentProcessor;
}
}
The created PaymentProcessor depends now on the passed Builder:
...
PaymentProcessorDirector director = new PaymentProcessorDirector();
PaymentProcessorBuilder builder = new PaypalRefundProcessorBuilder();
PaymentProcessor paymentProcessor = director.createPaymentProcessor(builder);
...
For each combination you can create a builder. If you pass the right builder to the director you get the wanted PaymentProcessor back.
Now the question how could you get the right builder. Therefore you can use a factory, that takes some event arguments and decides then which builder has to be made. This builder you pass in the director an get the wanted PaymentProcessor.
CAUTION: This is only one possible solution for this problem. Every solution has is advantages and disadvantages. To find the right solution you to balance the good and the bad things.
PS: Hope the syntax is correct. Im not a java developer.
EDIT:
You could interprete the director of the builder pattern as a PaymentProcessorFactory with the builder itself as strategy for building the parts of the PaymentProcessor
So i have a class that makes an array list for me and i need to access it in another class through a constructor but i don't know what to put into the constructor because all my methods in that class are just for manipulating that list. im either getting a null pointer exception or a out of bounds exception. ive tried just leaving the constructor empty but that dosent seem to help. thanks in advance. i would show you code but my professor is very strict on academic dishonesty so i cant sorry if that makes it hard.
You are confusing the main question, with a potential solution.
Main Question:
I have a class ArrayListOwnerClass with an enclosed arraylist property or field.
How should another class ArrayListFriendClass access that property.
Potential Solution:
Should I pass the arraylist from ArrayListOwnerClass to ArrayListFriendClass,
in the ArrayListFriendClass constructor ?
It depends on what the second class does with the arraylist.
Instead of passing the list thru the constructor, you may add functions to read or change, as public, the elements of the hidden internal arraylist.
Note: You did not specify a programming language. I'll use C#, altought Java, C++, or similar O.O.P. could be used, instead.
public class ArrayListOwnerClass
{
protected int F_Length;
protected ArrayList F_List;
public ArrayListOwnerClass(int ALength)
{
this.F_Length = ALength;
this.F_List = new ArrayList(ALength);
// ...
} // ArrayListOwnerClass(...)
public int Length()
{
return this.F_Length;
} // int Length(...)
public object getAt(int AIndex)
{
return this.F_List[AIndex];
} // object getAt(...)
public void setAt(int AIndex, object AValue)
{
this.F_List[AIndex] = AValue;
} // void setAt(...)
public void DoOtherStuff()
{
// ...
} // void DoOtherStuff(...)
// ...
} // class ArrayListOwnerClass
public class ArrayListFriendClass
{
public void UseArrayList(ArrayListOwnerClass AListOwner)
{
bool CanContinue =
(AListOwner != null) && (AListOwner.Length() > 0);
if (CanContinue)
{
int AItem = AListOwner.getAt(5);
DoSomethingWith(Item);
} // if (CanContinue)
} // void UseArrayList(...)
public void AlsoDoesOtherStuff()
{
// ...
} // void AlsoDoesOtherStuff(...)
// ...
} // class ArrayListFriendClass
Note, that I could use an indexed property.
I am working in Scout and need SmartField. For this I need to set up lookup for suggestions.
I see the example with creating Lookup Call and than implement in Lookup Service getConfiguredSqlSelect
but I use Hibernate to work with classes, so my question is how to connect Smart field with Hibernate object filled service?
create a new lookup call according to [1] with the following differences:
don't select AbstractSqlLookupService as a lookup servic super type, but AbstractLookupService
in the associated lookup service you now need to implement getDataByAll, getDataByKey, and getDataByText
to illustrate the following snippet should help:
public class TeamLookupService extends AbstractLookupService<String> implements ITeamLookupService {
private List<ILookupRow<String>> m_values = new ArrayList<>();
public TeamLookupService() {
m_values.add(new LookupRow<String>("CRC", "Costa Rica"));
m_values.add(new LookupRow<String>("HON", "Honduras"));
m_values.add(new LookupRow<String>("MEX", "Mexico"));
m_values.add(new LookupRow<String>("USA", "USA"));
}
#Override
public List<? extends ILookupRow<String>> getDataByAll(ILookupCall<String> call) throws ProcessingException {
return m_values;
}
#Override
public List<? extends ILookupRow<String>> getDataByKey(ILookupCall<String> call) throws ProcessingException {
List<ILookupRow<String>> result = new ArrayList<>();
for (ILookupRow<String> row : m_values) {
if (row.getKey().equals(call.getKey())) {
result.add(row);
}
}
return result;
}
...
[1] https://wiki.eclipse.org/Scout/Tutorial/4.0/Minicrm/Lookup_Calls_and_Lookup_Services#Create_Company_Lookup_Call