/*******************************************************************************
* Copyright 2017 Capital One Services, LLC and Bitwise, Inc.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package hydrograph.ui.propertywindow.propertydialog;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.slf4j.Logger;
import hydrograph.ui.common.util.ComponentCacheUtil;
import hydrograph.ui.common.util.Constants;
import hydrograph.ui.common.util.ImagePathConstant;
import hydrograph.ui.common.util.OSValidator;
import hydrograph.ui.common.util.XMLConfigUtil;
import hydrograph.ui.graph.model.Component;
import hydrograph.ui.graph.model.components.SubjobComponent;
import hydrograph.ui.graph.schema.propagation.SchemaData;
import hydrograph.ui.logging.factory.LogFactory;
import hydrograph.ui.propertywindow.constants.ELTProperties;
import hydrograph.ui.propertywindow.messagebox.ConfirmCancelMessageBox;
import hydrograph.ui.propertywindow.property.ELTComponenetProperties;
import hydrograph.ui.propertywindow.property.Property;
import hydrograph.ui.propertywindow.validators.ComponentValidator;
import hydrograph.ui.propertywindow.widgets.customwidgets.AbstractWidget;
import hydrograph.ui.propertywindow.widgets.customwidgets.schema.ELTSchemaGridWidget;
import hydrograph.ui.propertywindow.widgets.interfaces.IOperationClassDialog;
import hydrograph.ui.validators.impl.IValidator;
/**
*
* @author Bitwise
* Sep 07, 2015
*
*/
public class PropertyDialog extends Dialog implements IOperationClassDialog{
private static final Logger logger = LogFactory.INSTANCE.getLogger(PropertyDialog.class);
private Composite container;
private final LinkedHashMap<String, LinkedHashMap<String, ArrayList<Property>>> propertyTree;
private PropertyDialogBuilder propertyDialogBuilder;
private PropertyDialogButtonBar propertyDialogButtonBar;
private final String componentName;
private Button applyButton;
private boolean propertyChanged=false;
private final ELTComponenetProperties componentProperties;
private boolean isPropertyWindowValid;
private Map<String,String> toolTipErrorMessages;
private Component component;
private boolean isCancelButtonPressed = false;
private boolean closeDialog;
private boolean okPressed;
private String selectedTab;
private SchemaData schemaData;
private boolean isCancelPressed;
private Button okButton;
/**
* Create the dialog.
* @param parentShell
* @param propertyTree
* @param component
* @param ComponentProperties
*/
public PropertyDialog(LinkedHashMap<String, LinkedHashMap<String, ArrayList<Property>>> propertyTree,ELTComponenetProperties eltComponenetProperties,Map<String, String> toolTipErrorMessages, Component component) {
super(Display.getCurrent().getActiveShell());
this.propertyTree = propertyTree;
this.componentProperties = eltComponenetProperties;
componentName = (String) this.componentProperties.getComponentConfigurationProperty(ELTProperties.NAME_PROPERTY.propertyName());
this.component = component;
setShellStyle(SWT.CLOSE | SWT.TITLE | SWT.WRAP | SWT.APPLICATION_MODAL | SWT.RESIZE);
/**
* Initialize it with true, if any one of the property is invalid then mark this status as false
*/
isPropertyWindowValid = true;
this.toolTipErrorMessages = toolTipErrorMessages;
schemaData = new SchemaData();
}
/**
* Create contents of the dialog.
* @param parent
*/
@Override
protected Control createDialogArea(Composite parent) {
createPropertyDialogContainer(parent);
propertyDialogButtonBar = new PropertyDialogButtonBar(container);
propertyDialogBuilder = new PropertyDialogBuilder(container,propertyTree,componentProperties,propertyDialogButtonBar,component,this);
propertyDialogBuilder.buildPropertyWindow();
return container;
}
private void createPropertyDialogContainer(Composite parent) {
container = (Composite) super.createDialogArea(parent);
setPropertyDialogContainerLayout();
setPropertyDialogTitle();
}
private void setPropertyDialogContainerLayout() {
container.setLayout(new GridLayout(1, false));
}
private void setPropertyDialogTitle() {
container.getShell().setText(componentName + " - Properties");
}
/**
* Create contents of the button bar.
* @param parent
*/
@Override
protected void createButtonsForButtonBar(Composite parent) {
Button okButton = createOKButton(parent);
Button cancelButton = createCancelButton(parent);
createApplyButton(parent);
attachPropertyDialogButtonBarToEatchWidgetOnPropertyWindow(okButton,
cancelButton);
}
private void attachPropertyDialogButtonBarToEatchWidgetOnPropertyWindow(
Button okButton, Button cancelButton) {
propertyDialogButtonBar.setPropertyDialogButtonBar(okButton, applyButton, cancelButton);
}
private void createApplyButton(Composite parent) {
applyButton = createButton(parent, IDialogConstants.NO_ID,
"Apply", false);
disableApplyButton();
}
@Override
protected void buttonPressed(int buttonId) {
// If Apply Button pressed(3 is index of apply button);
if(buttonId == 3){
applyButton.setFocus();
applyButtonAction();
}
updateComponentValidityStatus();
super.buttonPressed(buttonId);
}
private void updateComponentValidityStatus() {
String statusString = null;
if(isPropertyWindowValid){
statusString = "VALID";
}
else{
statusString = "ERROR";
}
componentProperties.getComponentConfigurationProperties().put("validityStatus", statusString);
}
private void applyButtonAction() {
boolean windowValidityStaus = Boolean.TRUE;
boolean verifiedSchema = Boolean.TRUE;
for(AbstractWidget customWidget : propertyDialogBuilder.getELTWidgetList()){
LinkedHashMap<String, Object> properties= customWidget.getProperties();
if(properties != null){
windowValidityStaus = validateWidget(windowValidityStaus, customWidget,properties);
if (customWidget instanceof ELTSchemaGridWidget) {
verifiedSchema = customWidget.verifySchemaFile();
if (verifiedSchema){
savePropertiesInComponentModel(customWidget,properties);
}
} else{
savePropertiesInComponentModel(customWidget,properties);
}
}
}
isPropertyWindowValid = windowValidityStaus;
validateComponentState();
updateComponentValidityStatus();
propertyChanged=true;
disableApplyButton();
}
private void savePropertiesInComponentModel(AbstractWidget eltWidget,LinkedHashMap<String, Object> properties) {
LinkedHashMap<String, Object> tempPropert = properties;
LinkedHashMap<String, Object> componentConfigurationProperties = componentProperties.getComponentConfigurationProperties();
for(String propName : tempPropert.keySet()){
componentConfigurationProperties.put(propName, tempPropert.get(propName));
}
}
private void disableApplyButton() {
applyButton.setEnabled(false);
}
private Button createCancelButton(Composite parent) {
Button cancelButton = createButton(parent, IDialogConstants.CANCEL_ID,
IDialogConstants.CANCEL_LABEL, false);
return cancelButton;
}
private Button createOKButton(Composite parent) {
okButton=createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
true);
return okButton;
}
/**
* Return the initial size of the dialog.
*/
@Override
protected Point getInitialSize() {
return new Point(500,670);
}
protected Point getDefaultSize()
{
return getShell().computeSize(450, 620, true);
}
@Override
protected void okPressed() {
okButton.setFocus();
boolean windowValidityStaus = Boolean.TRUE;
boolean verifiedSchema = Boolean.TRUE;
for (AbstractWidget customWidget : propertyDialogBuilder.getELTWidgetList()) {
LinkedHashMap<String, Object> properties= customWidget.getProperties();
if (properties != null) {
windowValidityStaus = validateWidget(windowValidityStaus, customWidget,properties);
if (customWidget instanceof ELTSchemaGridWidget) {
verifiedSchema = customWidget.verifySchemaFile();
if (verifiedSchema){
savePropertiesInComponentModel(customWidget,properties);
}
} else{
savePropertiesInComponentModel(customWidget,properties);
}
}
}
if (applyButton.isEnabled())
propertyChanged = true;
isPropertyWindowValid = windowValidityStaus;
validateComponentState();
updateComponentValidityStatus();
okPressed = true;
if (verifiedSchema){
super.okPressed();
}
if(component.isContinuousSchemaPropogationAllow()&& !(component instanceof SubjobComponent))
component.setContinuousSchemaPropogationAllow(false);
}
/**
*
* press ok button
*
*/
public void pressOK(){
okPressed();
}
@Override
protected void cancelPressed() {
setCancelPressed(true);
boolean windowValidityStaus = Boolean.TRUE;
for (AbstractWidget customWidget : propertyDialogBuilder.getELTWidgetList()) {
Map<String, Object> properties= customWidget.getEltComponenetProperties().getComponentConfigurationProperties();
if (properties != null) {
windowValidityStaus = validateWidget(windowValidityStaus, customWidget,properties);
}
}
isPropertyWindowValid = windowValidityStaus;
validateComponentState();
updateComponentValidityStatus();
if (applyButton.isEnabled()) {
if (!isCancelButtonPressed) {
ConfirmCancelMessageBox confirmCancelMessageBox = new ConfirmCancelMessageBox(container);
MessageBox confirmCancleMessagebox = confirmCancelMessageBox.getMessageBox();
if (confirmCancleMessagebox.open() == SWT.OK) {
closeDialog = super.close();
}
} else {
closeDialog = super.close();
}
} else {
closeDialog = super.close();
}
}
private void validateComponentState() {
if(!ComponentValidator.INSTANCE.validate(component)){
isPropertyWindowValid = false;
}
}
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
String imagePath = null;
//TODO Please uncomment below code before build.
try{
newShell.setImage(ImagePathConstant.APP_ICON.getImageFromRegistry());
if(OSValidator.isMac()){
newShell.setMinimumSize(new Point(500, 500));
}else{
newShell.setMinimumSize(new Point(500, 525));
}
}catch(SWTError e){
logger.debug("Unable to access image" , e);
}
}
/**
*
* returns true if user made changes in property window
*
* @return boolean
*/
public boolean isPropertyChanged(){
return propertyChanged;
}
private boolean validateWidget(Boolean windowValidityStaus, AbstractWidget customWidget,Map<String, Object> properties) {
List<String> validators = ComponentCacheUtil.INSTANCE.getValidatorsForProperty(
(String) this.componentProperties.getComponentMiscellaneousProperty(Constants.COMPONENT_ORIGINAL_NAME),
customWidget.getPropertyName());
IValidator validator = null;
for (String validatorName : validators) {
try {
validator = (IValidator) Class.forName(Constants.VALIDATOR_PACKAGE_PREFIX + validatorName).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
logger.error("Failed to create validator", e);
throw new RuntimeException("Failed to create validator", e);
}
boolean status = validator.validateMap(properties, customWidget.getPropertyName(),schemaData.getInputSchema(component));
//NOTE : here if any of the property is not valid then whole component is not valid
if(status == false){
windowValidityStaus = Boolean.FALSE;
logger.debug("{} is not valid", customWidget.getPropertyName());
}
appendErrorMessage(customWidget, validator);
}
return windowValidityStaus;
}
private void appendErrorMessage(AbstractWidget customWidget, IValidator validator) {
if(toolTipErrorMessages.containsKey(customWidget.getPropertyName())){
String errorMessage = toolTipErrorMessages.get(customWidget.getPropertyName());
errorMessage = errorMessage + "\n" + validator.getErrorMessage();
}else{
if (!StringUtils.isBlank(validator.getErrorMessage())) {
toolTipErrorMessages.put(customWidget.getPropertyName(), validator.getErrorMessage());
}
}
}
@Override
public void pressCancel() {
isCancelButtonPressed = true;
cancelPressed();
}
@Override
public boolean close() {
if(!okPressed){
cancelPressed();
return closeDialog;
}else{
return super.close();
}
}
public String getSelectedTab() {
return selectedTab;
}
public void setSelectedTab(String selectedTab) {
this.selectedTab = selectedTab;
}
public boolean isCancelPressed() {
return isCancelPressed;
}
public void setCancelPressed(boolean isCancelPressed) {
this.isCancelPressed = isCancelPressed;
}
}