Method that returns two classes in java - java

I have two classes:
public class UnoLoginPageUi {
public final Input username = new Input("id=username");
public final Input password = new Input("id=password");
public final Button loginButton = new Button("name=login");
}
and
public class DuoLoginPageUi {
public final Input username = new Input("id=usernameField");
public final Input password = new Input("id=passwordField");
public final Button loginButton = new Button("id=submitButton");
}
and in one common class I want to make something like that:
public void loginUsingUsernameAndPassword(String username, String password, String pageType) {
getUi(pageType).username.waitForToBeDisplayed();
getUi(pageType).username.setValue(username);
getUi(pageType).password.setValue(password);
getUi(pageType).loginButton.click();
}
where getUi() is a method that gas argument pageType (which is UNO or DUO).
private Class getUi(String pageType) {
if (pageType.equals("UNO")) {
return new DuoLoginPageUi();
}
else if (pageType.equals("DUO")) {
return new UnoLoginPageUi;
}
return null;
}
However it doesn't work as this method need to in type of this two pages with selectors - how to deal with that ?

You can create a interface called LoginPageUi. And let your UnoLoginPageUi and DuoLoginPageUi implement that interface.
Then your getUi method will be private LoginPageUi getUi(String pageType).
Off topic: I would recommend to implement an enum instead of String pageType.

Create a common abstraction for the two classes
public abstract class LoginPageUi {
public final Input username = new Input("id=username");
public final Input password = new Input("id=password");
public final Button loginButton = new Button("name=login");
}
and have UnoLoginPageUi and DuoLoginPageUi extend that
public class UnoLoginPageUi extends LoginPageUi {
public static String getPageType() { return "UNO"; }
}
public class DuoLoginPageUi extends LoginPageUi {
public static String getPageType() { return "DUO"; }
}
The method would return the common abstraction
private LoginPageUi getUi(String pageType) {
if (pageType.equals(DuoLoginPageUi.getPageType())) {
return new DuoLoginPageUi();
}
else if (pageType.equals(UnoLoginPageUi.getPageType())) {
return new UnoLoginPageUi;
}
return null;
}
I also hope you realize that every time you call getUi(pageType) it is returning a new instance. by the time you call getUi(pageType).loginButton.click(); the instance returned has no values set.
Refactor:
public void loginUsingUsernameAndPassword(String username, String password, String pageType) {
LoginPageUi ui = getUi(pageType);
if (ui != null) {
ui.username.waitForToBeDisplayed();
ui.username.setValue(username);
ui.password.setValue(password);
ui.loginButton.click();
}
}

create Parent class or interface for both called UI:
public abstract class Ui{
}
public interface Ui{
}
and extend it:
public class UnoLoginPageUi extends Ui{
public final Input username = new Input("id=username");
public final Input password = new Input("id=password");
public final Button loginButton = new Button("name=login");
}
public class DuoLoginPageUi extends Ui {
public final Input username = new Input("id=usernameField");
public final Input password = new Input("id=passwordField");
public final Button loginButton = new Button("id=submitButton");
}
or
public class UnoLoginPageUi implements Ui{
public final Input username = new Input("id=username");
public final Input password = new Input("id=password");
public final Button loginButton = new Button("name=login");
}
public class DuoLoginPageUi implements Ui {
public final Input username = new Input("id=usernameField");
public final Input password = new Input("id=passwordField");
public final Button loginButton = new Button("id=submitButton");
}
then return parent reference as:
private Ui getUi(String pageType) {
if (pageType.equals("UNO")) {
return new DuoLoginPageUi();
}
else if (pageType.equals("DUO")) {
return new UnoLoginPageUi;
}
return null;
}

Related

Consumer with Polymorphism in interface

Finally I solve problem by myself
It turns out that consumers can transform
and Through the interface let my xxx_dialogs and Compulsory use openDialog function.
Data bean start for product, Customer
public class Prod extends MyBean {
private String P_NO = "";
private setP_NO(String p_no){
P_NO= p_no;
}
private String getP_NO(){
return P_NO;
}
}
public class Cust extends MyBean {
private String CUST_NO = "";
....
}
public class MyView{
  TextField textFieldP_NO;
  Button btnProd;
  Button btnCust;
  public MyView (){
//...constructor...
}
btnProd.addClickListener(e -> {
Prod_Dialog p_dlg = new Prod_Dialog();
//fix before
//p_dlg.openDialog(p -> textFieldP_NO.setValue(p.getP_NO()));
//fix after
p_dlg.openDialog(p -> textFieldP_NO.setValue(((PROD_Dialog.Prod) p).getP_NO()));
});
btnCust.addClickListener(e -> {
Cust_Dialog c_dlg = new Cust_Dialog();
//fix before
//c_dlg.openDialog(c -> textFieldP_NO.setValue(c.getCUST_NO()));
//fix after
c_dlg.openDialog(c -> textFieldP_NO.setValue(((CUST_Dialog.Cust) c).getCUST_NO()));
});
}
[Interface] fix parametere Consumer can Polymorphism
public interface BaseDialog {
//fix before just for prodct. That's bad....
//public abstract void openDialog(Consumer<Prod> selectionAction);
//fix after that can service any MyBean...
public abstract void openDialog(Consumer<? extends MyBean> selectionAction);
}
[Dialog] with Prod_Dialog and cust_Dialog thougth clickok method pass Consumer<Prod> or Consumer<Cust>
//fix before
//public class Prod_Dialog {
//fix after
public class Prod_Dialog implements BaseDialog{
private Button btnOk;
...
//fix before
//public void openDialog(Consumer<Prod> selectionAction) {
//fix after
public void openDialog(Consumer<? extends MyBean> selectionAction) {
btnOk.addClickListener(e -> {
//fix before
// Prod sel_prod = grid.asSingleSelect().getValue();
// String p_no = sel_prod.getP_NO(); //get user selected p_no
// Prod prod = new Prod();
// prod.setP_NO(p_no);
// selectionAction.accept(prod);
//fix after that is magic point for me, by Consumer Transformation
clickOK((Consumer<Prod>) selectionAction);
}
}
public void clickOK(Consumer<Prod> selectionAction) {
Prod sel_prod = grid.asSingleSelect().getValue();
String p_no = sel_prod.getP_NO(); //get user selected p_no
Prod prod = new Prod();
prod.setP_NO(p_no);
selectionAction.accept(prod);
}
}
public class Cust_Dialog implements BaseDialog{
private Button btnOk;
...
public void openDialog(Consumer<? extends MyBean> selectionAction) {
btnOk.addClickListener(e -> {
//fix before
// Cust sel_cust = grid.asSingleSelect().getValue();
// String c_no = sel_cust.getCUST_NO(); //get user selected p_no
// Cust cust = new Cust();
// Cust.setCUST_NO(c_no);
// selectionAction.accept(cust);
//fix after
clickOK((Consumer<Cust>) selectionAction); //that is magic point for me, by Consumer Transformation
}
}
public void clickOK(Consumer<Cust> selectionAction) {
Prod sel_cust = grid.asSingleSelect().getValue();
String c_no = sel_prod.getCUST_NO(); //get user selected p_no
Cust cust = new Cust();
cust.setCUST_NO(c_no);
selectionAction.accept(cust); //that is magic point for me
}
}
Your working implementing class code method signature
public void openDialog(Consumer<PROD> selectionAction)
is not identical to the interface signature
public abstract void openDialog(Consumer<? extends MyBean> selectionAction);
Do not write abstract in the interface signature declaration (they are public and abstract by default)!
Arguments to the methods will / must / are - always be identical too!
Implementing class code method signature should be almost and if not , totally identical in the interface.

How to implement builder inside my already defined class

I am trying to convert my class to support builder in order to prettify my code, this is the code I am using and I try to define my method called addSMTPIntegration to use builder.
this is my class:
public class IntegrationsPage extends SettingsTab {
private static final By newIntegrationBth = Locators.findBy("settings_page_integrations_page_add_new_button");
private IntegrationsTable integrationsTable;
private SmtpIntegrationForm smtpIntegrationForm;
private ConfirmPopup confirmPopup;
public IntegrationsPage(DriverWrapper driver){
super(driver, "integrations",newIntegrationBth);
integrationsTable = new IntegrationsTable(driver);
smtpIntegrationForm = new SmtpIntegrationForm(driver);
confirmPopup = new ConfirmPopup(driver);
}
public void addSMTPIntegration(String name, String server, String port, String fromAddress, boolean mode, String userName, String password){
clickNewIntegrationButton();
smtpIntegrationForm.chooseIntegration(IntegrationType.SMTP);
smtpIntegrationForm.setIntegrationName(name);
smtpIntegrationForm.setIntegrationServer(server);
smtpIntegrationForm.setIntegrationPort(port);
smtpIntegrationForm.setIntegrationFromAddress(fromAddress);
smtpIntegrationForm.setIntegrationAuth(mode);
smtpIntegrationForm.setIntegrationUserName(userName);
smtpIntegrationForm.setIntegrationPassword(password);
smtpIntegrationForm.clickSaveButton();
LOG.i("SMTP configuration passed successfully");
}
private void clickNewIntegrationButton(){
clickButton(newIntegrationBth);
}
public IntegrationsRow waitIntegrationRowTable(String configurationName) {
return integrationsTable.waitRowDisplay(configurationName);
}
public boolean deleteIntegration(String integrationName) {
integrationsTable.findRow(integrationName).clickRow();
integrationsTable.delete(integrationName);
confirmPopup.clickYes();
return integrationsTable.findRow(integrationName) == null;
}
}
I am trying to define my addSMTPIntegration method to support builder in a manner that I would be able to build it in the following way:
smtpIntegrationForm.chooseIntegration(IntegrationType.SMTP).setIntegrationName(name).setIntegrationServer(server).... etc
This is my smtpIntegrationForm class:
public class SmtpIntegrationForm extends IntegrationCommonSection {
private static final By integrationServerBy = Locators.findBy("settings_page_integrations_page_integration_server_name_txt");
private static final By integrationPortBy = Locators.findBy("settings_page_integrations_page_integration_port_txt");
private static final By integrationFromAddressBy = Locators.findBy("settings_page_integrations_page_integration_from_address_txt");
SmtpIntegrationForm(DriverWrapper driver){
super(driver);
}
void setIntegrationServer(String server){
setText(integrationServerBy, server);
}
void setIntegrationPort(String port){
setText(integrationPortBy, port);
}
void setIntegrationFromAddress(String address){
setText(integrationFromAddressBy, address);
}
void chooseIntegration(IntegrationType integrationType){
clickButton(By.cssSelector("li[class~='qa_" + integrationType.value + "']"));
}
and this is IntegrationCommonSection class:
class IntegrationCommonSection extends PageElement {
private static final By integrationNameBy = Locators.findBy("settings_page_integrations_page_integration_name_txt");
private static final By integrationAuthBy = Locators.findBy("settings_page_integrations_page_integration_auth_bth");
private static final By integrationUserNameBy = Locators.findBy("settings_page_integrations_page_integration_username_txt");
private static final By integrationPasswordBy = Locators.findBy("settings_page_integrations_page_integration_password_txt");
private static final By integrationSaveBthBy = Locators.findBy("settings_page_integrations_page_integration_save_bth");
private static final By integrationTestBthBy = Locators.findBy("settings_page_integrations_page_integration_test_bth");
IntegrationCommonSection(DriverWrapper driver){
super(driver);
}
void setIntegrationName(String name){
clearAndSetCharacters(integrationNameBy, name);
}
void setIntegrationAuth(boolean mode){ //true - with auth, false - no auth
if(!isCheckBoxEnabled(integrationAuthBy) && mode) {
clickButton(integrationAuthBy);
}
}
void setIntegrationUserName(String userName){
setText(integrationUserNameBy, userName);
}
void setIntegrationPassword(String password){
setText(integrationPasswordBy, password);
}
void clickSaveButton(){
clickButton(integrationSaveBthBy);
}
void clickTestButton(){
clickButton(integrationTestBthBy);
}
}
just return "this" :
SmtpIntegrationForm setIntegrationServer(String server){
setText(integrationServerBy, server);
return this;
}
In order to do that, you need to modify the methods of SmtpIntegrationForm with the return of this object so that you can construct the statements in a builder pattern. There is nothing you can do in addSMTPIntegration() method to achieve this.
chooseIntegration(), setIntegrationName(), setIntegrationServer(), etc. methods inside SmtpIntegrationForm should have return type of SmtpIntegrationForm and the last statement in these methods should be return this; in order for you to achieve this.
Make the changes as:
public class SmtpIntegrationForm extends IntegrationCommonSection {
private static final By integrationServerBy = Locators.findBy("settings_page_integrations_page_integration_server_name_txt");
private static final By integrationPortBy = Locators.findBy("settings_page_integrations_page_integration_port_txt");
private static final By integrationFromAddressBy = Locators.findBy("settings_page_integrations_page_integration_from_address_txt");
SmtpIntegrationForm(DriverWrapper driver){
super(driver);
}
SmtpIntegrationForm setIntegrationServer(String server){
setText(integrationServerBy, server);
return this;
}
SmtpIntegrationForm setIntegrationPort(String port){
setText(integrationPortBy, port);
return this;
}
SmtpIntegrationForm setIntegrationFromAddress(String address){
setText(integrationFromAddressBy, address);
return this;
}
SmtpIntegrationForm chooseIntegration(IntegrationType integrationType){
clickButton(By.cssSelector("li[class~='qa_" + integrationType.value + "']"));
return this;
}
}

command pattern, why does this not work

I am implementing a command pattern in android.
This is what I have right now. For some reason this does not run. It is like the AddUserRequest is getting garbage collected for some reason.
RequestManager.java:
public class RequestManager extends BroadcastReceiver {
private static final RequestManager instance = new RequestManager();
private boolean isConnected = false;
private static ArrayList<Request> requestQueue = new ArrayList<Request>();
private RequestManager() {
}
/* singleton class */
public static RequestManager getInstance() {
return instance;
}
public void invokeRequest(Request request) {
request.execute(); // only to test this, this will change
return;
}
}
AddUserRequest.java
public class AddUserRequest extends InsertionRequest {
User user;
public AddUserRequest(User user) {
this.user = user;
}
public void execute() {
System.out.println("TEST!!!");
}
}
Request.java:
public abstract class Request {
public abstract void execute();
}
}
InsertionRequest.java
public abstract class InsertionRequest extends Request {
}
RequestManagerTest.java
public class RequestManagerTest extends ActivityInstrumentationTestCase2 {
public RequestManagerTest(){
super(MainActivity.class);
}
public void testAddUserRequest() {
User user = new User();
user.setName("Tester12345");
AddUserRequest request = new AddUserRequest(user);
RequestManager.getInstance().invokeRequest(request);
}
}
For some reason this does not print "TEST!!!" and for the life of me I cannot figure out why. I looked in the debug log and everytime request.execute() in RequestManager.java gets called there is a "GC Explicit..." which I suspect has to do with garbage collection. What is the proper way to do what I am trying to do?

Java Generics in Builder

How can I use generics propery in my particular case? The code first, then the explanation:
AbstractConstraint.java
public abstract class AbstractConstraint {
public abstract Constraint[] getConstraints();
}
AccountConstraint.java
public class AccountConstraint extends AbstractConstraint {
private Constraint<Range<Integer>> accountIdConstraint;
private Constraint<String> usernameConstraint;
private Constraint<String> passwordConstraint;
private Constraint<String> emailConstraint;
private AccountConstraint(Builder builder) {
this.accountIdConstraint = builder.accountIdConstraint;
this.usernameConstraint = builder.usernameConstraint;
this.passwordConstraint = builder.passwordConstraint;
this.emailConstraint = builder.emailConstraint;
}
#Override
public Constraint[] getConstraints() {
return new Constraint[] {
this.accountIdConstraint,
this.usernameConstraint,
this.passwordConstraint,
this.emailConstraint
};
}
public static class Builder extends ConstraintBuilder<AccountConstraint> {
private Constraint<Range<Integer>> accountIdConstraint;
private Constraint<String> usernameConstraint;
private Constraint<String> passwordConstraint;
private Constraint<String> emailConstraint;
public Builder() {
this.accountIdConstraint = null;
this.usernameConstraint = null;
this.passwordConstraint = null;
this.emailConstraint = null;
init();
}
public Builder accountId(final int val) {
this.accountIdConstraint = new Constraint<>(operation, truthed, new Range<>(val), "accountId");
return this;
}
public Builder accountId(final int min, final int max) {
this.accountIdConstraint = new Constraint<>(operation, truthed, new Range<>(min, max), "accountId");
return this;
}
public Builder accountId(final Range<Integer> accountId) {
this.accountIdConstraint = new Constraint<>(operation, truthed, accountId, "accountId");
return this;
}
public Builder username(final String username) {
this.usernameConstraint = new Constraint<>(operation, truthed, username, "username");
return this;
}
public Builder email(final String email) {
this.emailConstraint = new Constraint<>(operation, truthed, email, "email");
return this;
}
#Override
public AccountConstraint build() {
return new AccountConstraint(this);
}
}
}
ConstraintBuilder.java
public abstract class ConstraintBuilder<T> {
protected boolean truthed;
protected Operation operation;
protected void init() {
truthed = true;
operation = Operation.IS;
}
public ConstraintBuilder not() {
truthed = false;
return this;
}
public ConstraintBuilder like() {
operation = Operation.LIKE;
return this;
}
public abstract T build();
}
I want to be able to call new AccountConstraint.Builder().not().username("test"); but this is not possible as I lose the 'reference to the builder' at new AccountConstraint.Builder().not()., ie. I cannot select username("test") anymore.
In what ways could I fix this? I do want that the AccountBuilder.Builder extends ConstraintBuilder<AccountConstraint.Builder> such that I do not have to duplicate the commonly shared methods then.
Regards.
EDIT: I managed to get it working:
See the answer below for the changes.
I hope I haven't broken any Java fundamentals with this solution, I hope it is more of a solution than a dirty hack.
I would be pleased if someone could review this edit.
I think this should work:
Builder builder = (Builder) new AccountConstraint.Builder().not();
builder = builder.username("test");
Your issue is that:
new AccountConstraint.Builder().not()
returns a ConstrainBuilder<T>, which doesn't necessarily have access to username(final String). So, you cast it to a Builder builder, and then call username(final String) on builder.
EDIT:
You can turn this into one line:
((Builder) (new AccountConstraint.Builder().not())).username("test");
EDIT 2:
You could override not() in Builder: make it call super.not() and cast the return to a Builder. As in:
public Builder not()
{
return (Builder) super.not();
}
If casting is acceptable, an alternative to Steve's answer would be to override methods like not() in Builder and narrow the type like this:
public Builder not() {
return (Builder) super.not();
}
That way the caller doesn't have to cast each time.
You probably need recursive generics.
Something like this should work:
public abstract class ConstraintBuilder<T, B extends ConstraintBuilder<T,B>> {
private final Class<B> concreteBuilderType;
public ConstraintBuilder(Class<B> concreteBuilderType) {
if (!concreteBuilderType.isInstance(this)) {
throw new IllegalArgumentException("Wrong type");
}
this.concreteBuilderType = concreteBuilderType;
}
...
public B not() {
truthed = false;
return concreteBuilderType.cast(this);
}
}
The concrete Builder() constructor would have to call super(Builder.class).

Multi-level Generics

I am trying to write a class as:
public class Article<T<? extends ManageGenericArticleInDTO>, U> implements Serializable {
private T<? extends ManageGenericArticleInDTO> userInput;
private U severData;
public Article<T<? extends ManageGenericArticleInDTO>, U>() {
super();
}
public void setUserInput(T<? extends ManageGenericArticleInDTO> userInput) {
this.userInput = userInput;
}
public T<? extends ManageGenericArticleInDTO> getUserInput() {
return userInput;
}
public void setSeverData(U severData) {
this.severData = severData;
}
public U getSeverData() {
return severData;
}
}
So that I can write these:
Article<UpdateManageArticleInDTO<ManageGenericArticleInDTO>, UpdateCentralPOSMArticleDTO> article = new Article<UpdateManageArticleInDTO<ManageGenericArticleInDTO>, UpdateCentralPOSMArticleDTO>();
Article<AddManageArticleInDTO<ManageCentralPOSMArticleInDTO>, AddArticleStepDTO> article = new Article<AddManageArticleInDTO<ManageCentralPOSMArticleInDTO>, AddArticleStepDTO>(); // ManageCentralPOSMArticleInDTO extends ManageGenericArticleInDTO
I am getting compilation error that Error(7,32): > expected, Error(7,33): illegal start of type etc. In my understanding the Type reference will be replaced by the actual class., Can't I define the class in this?
If I do this:
public class AddArticleInBean<T, U> implements Serializable {
private T userInput;
private U severData;
public AddArticleInBean() {
super();
}
public void setUserInput(T userInput) {
this.userInput = userInput;
}
public T getUserInput() {
return userInput;
}
public void setSeverData(U severData) {
this.severData = severData;
}
public U getSeverData() {
return severData;
}
}
This errors are not anymore appearing, but I am getting warning that T and U are non-serializable.
I think you are missing opening and closing brackets
It should be,
Article<UpdateManageArticleInDTO<ManageGenericArticleInDTO>, UpdateCentralPOSMArticleDTO> article = new Article<UpdateManageArticleInDTO<ManageGenericArticleInDTO>, UpdateCentralPOSMArticleDTO>();
Article<AddManageArticleInDTO<ManageCentralPOSMArticleInDTO>, AddArticleStepDTO> article = new Article<AddManageArticleInDTO<ManageCentralPOSMArticleInDTO>, AddArticleStepDTO>();

Categories

Resources