/*
* Copyright (c) 2011, grossmann
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the jo-widgets.org nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL jo-widgets.org BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package org.jowidgets.impl.widgets.composed;
import org.jowidgets.api.password.IPasswordChangeExecutor;
import org.jowidgets.api.password.IPasswordChangeResult;
import org.jowidgets.api.toolkit.Toolkit;
import org.jowidgets.api.types.InputDialogDefaultButtonPolicy;
import org.jowidgets.api.widgets.IButton;
import org.jowidgets.api.widgets.IComposite;
import org.jowidgets.api.widgets.IContainer;
import org.jowidgets.api.widgets.IFrame;
import org.jowidgets.api.widgets.IInputField;
import org.jowidgets.api.widgets.IPasswordChangeDialog;
import org.jowidgets.api.widgets.IProgressBar;
import org.jowidgets.api.widgets.IValidationResultLabel;
import org.jowidgets.api.widgets.blueprint.IInputFieldBluePrint;
import org.jowidgets.api.widgets.descriptor.setup.IPasswordChangeDialogSetup;
import org.jowidgets.common.image.IImageConstant;
import org.jowidgets.common.widgets.controller.IActionListener;
import org.jowidgets.common.widgets.layout.MigLayoutDescriptor;
import org.jowidgets.i18n.api.IMessage;
import org.jowidgets.tools.layout.MigLayoutFactory;
import org.jowidgets.tools.widgets.blueprint.BPF;
import org.jowidgets.tools.widgets.wrapper.WindowWrapper;
import org.jowidgets.util.Assert;
import org.jowidgets.util.EmptyCheck;
import org.jowidgets.util.EmptyCompatibleEquivalence;
import org.jowidgets.util.event.CancelObservable;
import org.jowidgets.validation.IValidationConditionListener;
import org.jowidgets.validation.IValidationResult;
import org.jowidgets.validation.IValidationResultBuilder;
import org.jowidgets.validation.IValidator;
import org.jowidgets.validation.ValidationResult;
import org.jowidgets.validation.tools.MandatoryValidator;
public final class PasswordChangeDialogImpl extends WindowWrapper implements IPasswordChangeDialog {
private static final IMessage OLD_PASSWORD = Messages.getMessage("PasswordChangeDialogImpl.oldPassword");
private static final IMessage NEW_PASSWORD = Messages.getMessage("PasswordChangeDialogImpl.newPassword");
private static final IMessage NEW_PASSWORD_REPEAT = Messages.getMessage("PasswordChangeDialogImpl.newPasswordRepeat");
private static final IMessage FILL_MANDATORY_FIELDS = Messages.getMessage("PasswordChangeDialogImpl.fillMandatoryFields");
private static final IMessage TRY_TO_CHANGE_PASSWORD = Messages.getMessage("PasswordChangeDialogImpl.tryToChangePassword");
private static final IMessage PASSWORDS_EQUAL = Messages.getMessage("PasswordChangeDialogImpl.passwordsEqual");
private static final IMessage REPEAT_PASSWORD = Messages.getMessage("PasswordChangeDialogImpl.repeatPassword");
private static final IMessage PASSWORD_REPEAT_MISMATCH = Messages.getMessage("PasswordChangeDialogImpl.passwordRepeatMissmatch");
private static final IMessage PASSWORD_CHANGED = Messages.getMessage("PasswordChangeDialogImpl.passwordChanged");
private final String title;
private final IImageConstant icon;
private final IValidationResultLabel validationResultLabel;
private final IInputField<String> oldPassword;
private final IInputField<String> newPassword;
private final IInputField<String> newPasswordRepeat;
private final IButton cancelButton;
private final IButton okButton;
private final IProgressBar progressBar;
private final IPasswordChangeExecutor executor;
public PasswordChangeDialogImpl(final IFrame dialog, final IPasswordChangeDialogSetup setup) {
super(dialog);
Assert.paramNotNull(dialog, "dialog");
Assert.paramNotNull(setup, "setup");
Assert.paramNotNull(setup.getExecutor(), "setup.getExecutor()");
this.title = setup.getTitle();
this.icon = setup.getIcon();
this.executor = setup.getExecutor();
dialog.setLayout(new MigLayoutDescriptor("0[grow, 0::]0", "0[grow, 0::][]0"));
final IComposite content = dialog.add(BPF.scrollComposite(), MigLayoutFactory.GROWING_CELL_CONSTRAINTS + ",wrap");
this.progressBar = dialog.add(BPF.progressBar().setIndeterminate(true), "growx, w 0::, h 10!");
progressBar.setVisible(false);
content.setLayout(new MigLayoutDescriptor("[][grow, 160::]", "[20!]25[]10[][]15[grow]"));
this.validationResultLabel = content.add(BPF.validationResultLabel(), "span 2, growx, w 0::, wrap");
this.oldPassword = addInputField(content, OLD_PASSWORD.get(), setup.getPasswordMaxLength());
this.newPassword = addInputField(content, NEW_PASSWORD.get(), setup.getPasswordMaxLength());
this.newPasswordRepeat = addInputField(content, NEW_PASSWORD_REPEAT.get(), setup.getPasswordMaxLength());
final IValidator<String> passwordValidator = setup.getPasswordValidator();
if (passwordValidator != null) {
newPassword.addValidator(passwordValidator);
}
final IComposite buttonBar = content.add(BPF.composite(), "alignx r, aligny b, span 2");
buttonBar.setLayout(new MigLayoutDescriptor("0[][]0", "0[]0"));
this.okButton = buttonBar.add(setup.getOkButton(), "sg bg");
this.cancelButton = buttonBar.add(setup.getCancelButton(), "sg bg");
cancelButton.addActionListener(new IActionListener() {
@Override
public void actionPerformed() {
setVisible(false);
}
});
okButton.addActionListener(new IActionListener() {
@Override
public void actionPerformed() {
changePassword();
}
});
if (InputDialogDefaultButtonPolicy.OK == setup.getDefaultButtonPolicy()) {
dialog.setDefaultButton(okButton);
}
else if (InputDialogDefaultButtonPolicy.CANCEL == setup.getDefaultButtonPolicy()) {
dialog.setDefaultButton(cancelButton);
}
validate();
}
private IInputField<String> addInputField(final IContainer content, final String label, final int maxLength) {
content.add(BPF.textLabel(label).alignRight(), "alignx r");
final IInputFieldBluePrint<String> inputFieldBp = BPF.inputFieldString().setPasswordPresentation(true);
inputFieldBp.setMaxLength(maxLength);
final IInputField<String> result = content.add(inputFieldBp, "growx, w 0::, wrap");
result.addValidator(new MandatoryValidator<String>(ValidationResult.infoError(FILL_MANDATORY_FIELDS.get())));
result.addValidationConditionListener(new IValidationConditionListener() {
@Override
public void validationConditionsChanged() {
validate();
}
});
return result;
}
private void validate() {
final IValidationResultBuilder builder = ValidationResult.builder();
builder.addResult(oldPassword.validate());
if (newPassword.hasModifications()) {
builder.addResult(newPassword.validate().withContext(NEW_PASSWORD.get()));
}
builder.addResult(newPasswordRepeat.validate());
builder.addResult(validatePasswordEquality());
final IValidationResult validationResult = builder.build();
validationResultLabel.setResult(validationResult);
if (validationResult.isValid()) {
okButton.setEnabled(true);
okButton.setToolTipText(null);
}
else {
okButton.setEnabled(false);
okButton.setToolTipText(validationResult.getWorstFirst().getText());
}
}
private IValidationResult validatePasswordEquality() {
final String oldPasswordValue = oldPassword.getValue();
final String newPasswordValue = newPassword.getValue();
final String newPasswordRepeatValue = newPasswordRepeat.getValue();
if (!EmptyCheck.isEmpty(newPasswordValue) && newPasswordValue.equals(oldPasswordValue)) {
return ValidationResult.error(PASSWORDS_EQUAL.get());
}
if (!EmptyCompatibleEquivalence.equals(newPasswordRepeatValue, newPasswordValue)) {
if (newPasswordRepeatValue != null
&& newPasswordValue != null
&& newPasswordValue.length() > newPasswordRepeatValue.length()) {
return ValidationResult.infoError(REPEAT_PASSWORD.get());
}
else {
return ValidationResult.error(PASSWORD_REPEAT_MISMATCH.get());
}
}
else {
return ValidationResult.ok();
}
}
private void changePassword() {
validationResultLabel.setResult(ValidationResult.infoError(TRY_TO_CHANGE_PASSWORD.get()));
setControlsEnabled(false);
progressBar.setVisible(true);
final CancelObservable cancelObservable = new CancelObservable();
final IActionListener cancelListener = new IActionListener() {
@Override
public void actionPerformed() {
cancelObservable.fireCanceledEvent();
}
};
final IPasswordChangeResult resultCallback = new IPasswordChangeResult() {
@Override
public void success() {
finishedCommon();
setVisible(false);
Toolkit.getMessagePane().showInfo(title, icon, PASSWORD_CHANGED.get());
}
@Override
public void error(final String errorText) {
finishedCommon();
validationResultLabel.setResult(ValidationResult.error(errorText));
}
private void finishedCommon() {
cancelButton.removeActionListener(cancelListener);
progressBar.setVisible(false);
setControlsEnabled(true);
}
};
cancelButton.addActionListener(cancelListener);
executor.changePassword(resultCallback, oldPassword.getValue(), newPassword.getValue(), cancelObservable);
}
private void setControlsEnabled(final boolean enabled) {
oldPassword.setEnabled(enabled);
newPassword.setEnabled(enabled);
newPasswordRepeat.setEnabled(enabled);
okButton.setEnabled(enabled);
}
}