/* * Copyright 2017 Red Hat, Inc. and/or its affiliates. * * 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 org.drools.workbench.screens.guided.dtable.client.wizard.column.plugins; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; import javax.enterprise.context.Dependent; import javax.enterprise.event.Event; import javax.inject.Inject; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.IsWidget; import org.drools.workbench.models.datamodel.oracle.DataType; import org.drools.workbench.models.datamodel.oracle.FieldAccessorsAndMutators; import org.drools.workbench.models.datamodel.rule.BaseSingleFieldConstraint; import org.drools.workbench.models.guided.dtable.shared.model.BRLRuleModel; import org.drools.workbench.models.guided.dtable.shared.model.CompositeColumn; import org.drools.workbench.models.guided.dtable.shared.model.ConditionCol52; import org.drools.workbench.models.guided.dtable.shared.model.DTCellValue52; import org.drools.workbench.models.guided.dtable.shared.model.GuidedDecisionTable52; import org.drools.workbench.models.guided.dtable.shared.model.LimitedEntryConditionCol52; import org.drools.workbench.models.guided.dtable.shared.model.Pattern52; import org.drools.workbench.screens.guided.dtable.client.resources.i18n.GuidedDecisionTableErraiConstants; import org.drools.workbench.screens.guided.dtable.client.widget.Validator; import org.drools.workbench.screens.guided.dtable.client.widget.table.utilities.CellUtilities; import org.drools.workbench.screens.guided.dtable.client.widget.table.utilities.ColumnUtilities; import org.drools.workbench.screens.guided.dtable.client.wizard.column.NewGuidedDecisionTableColumnWizard; import org.drools.workbench.screens.guided.dtable.client.wizard.column.commons.HasAdditionalInfoPage; import org.drools.workbench.screens.guided.dtable.client.wizard.column.commons.HasFieldPage; import org.drools.workbench.screens.guided.dtable.client.wizard.column.commons.HasPatternPage; import org.drools.workbench.screens.guided.dtable.client.wizard.column.commons.HasValueOptionsPage; import org.drools.workbench.screens.guided.dtable.client.wizard.column.pages.AdditionalInfoPage; import org.drools.workbench.screens.guided.dtable.client.wizard.column.pages.CalculationTypePage; import org.drools.workbench.screens.guided.dtable.client.wizard.column.pages.FieldPage; import org.drools.workbench.screens.guided.dtable.client.wizard.column.pages.OperatorPage; import org.drools.workbench.screens.guided.dtable.client.wizard.column.pages.PatternPage; import org.drools.workbench.screens.guided.dtable.client.wizard.column.pages.ValueOptionsPage; import org.drools.workbench.screens.guided.dtable.client.wizard.column.plugins.commons.AdditionalInfoPageInitializer; import org.drools.workbench.screens.guided.dtable.client.wizard.column.plugins.commons.BaseDecisionTableColumnPlugin; import org.drools.workbench.screens.guided.dtable.client.wizard.column.plugins.commons.DefaultWidgetFactory; import org.drools.workbench.screens.guided.dtable.client.wizard.column.plugins.commons.LimitedWidgetFactory; import org.drools.workbench.screens.guided.dtable.client.wizard.column.plugins.commons.PatternWrapper; import org.drools.workbench.screens.guided.dtable.client.wizard.column.plugins.commons.ValueOptionsPageInitializer; import org.jboss.errai.ui.client.local.spi.TranslationService; import org.kie.workbench.common.widgets.client.datamodel.AsyncPackageDataModelOracle; import org.uberfire.ext.widgets.core.client.wizards.WizardPage; import org.uberfire.ext.widgets.core.client.wizards.WizardPageStatusChangeEvent; import static org.drools.workbench.screens.guided.dtable.client.wizard.column.pages.common.DecisionTableColumnViewUtils.nil; @Dependent public class ConditionColumnPlugin extends BaseDecisionTableColumnPlugin implements HasFieldPage, HasPatternPage, HasValueOptionsPage, HasAdditionalInfoPage { private PatternPage<ConditionColumnPlugin> patternPage; private CalculationTypePage calculationTypePage; private FieldPage<ConditionColumnPlugin> fieldPage; private OperatorPage operatorPage; private AdditionalInfoPage<ConditionColumnPlugin> additionalInfoPage; private ValueOptionsPage<ConditionColumnPlugin> valueOptionsPage; private PatternWrapper patternWrapper; private ConditionCol52 editingCol; private int constraintValue; private Boolean valueOptionsPageCompleted; private Pattern52 editingPattern; @Inject public ConditionColumnPlugin(final PatternPage<ConditionColumnPlugin> patternPage, final CalculationTypePage calculationTypePage, final FieldPage<ConditionColumnPlugin> fieldPage, final OperatorPage operatorPage, final ValueOptionsPage<ConditionColumnPlugin> valueOptionsPage, final AdditionalInfoPage<ConditionColumnPlugin> additionalInfoPage, final Event<WizardPageStatusChangeEvent> changeEvent, final TranslationService translationService) { super(changeEvent, translationService); this.patternPage = patternPage; this.calculationTypePage = calculationTypePage; this.fieldPage = fieldPage; this.operatorPage = operatorPage; this.valueOptionsPage = valueOptionsPage; this.additionalInfoPage = additionalInfoPage; } @Override public String getTitle() { return translate(GuidedDecisionTableErraiConstants.ConditionColumnPlugin_AddNewConditionSimpleColumn); } @Override public void init(NewGuidedDecisionTableColumnWizard wizard) { super.init(wizard); setupDefaultValues(); } @Override public List<WizardPage> getPages() { return new ArrayList<WizardPage>() {{ add(patternPage); if (isExtendedEntryTable()) { add(calculationTypePage); } add(fieldPage); add(operatorPage); add(initializedValueOptionsPage()); add(initializedAdditionalInfoPage()); }}; } @Override public Boolean generateColumn() { if (!isValid()) { return false; } prepareValues(); appendColumn(); return true; } @Override public Type getType() { return Type.BASIC; } void appendColumn() { final Pattern52 pattern = editingPattern(); presenter.appendColumn(pattern, editingCol()); } public Pattern52 editingPattern() { editingPattern.setFactType(patternWrapper().getFactType()); editingPattern.setBoundName(patternWrapper().getBoundName()); editingPattern.setNegated(patternWrapper().isNegated()); editingPattern.setEntryPointName(patternWrapper().getEntryPointName()); return editingPattern; } private Pattern52 extractEditingPattern() { final String factType = patternWrapper().getFactType(); final String boundName = patternWrapper().getBoundName(); final Optional<Pattern52> pattern; if (!patternWrapper().isNegated()) { pattern = Optional.ofNullable(model().getConditionPattern(boundName)); } else { pattern = model() .getPatterns() .stream() .filter(Pattern52::isNegated) .filter(p -> p.getFactType().equals(factType)) .findFirst(); } return pattern.orElse(emptyPattern()); } void prepareValues() { if (constraintValue() == BaseSingleFieldConstraint.TYPE_PREDICATE) { editingCol().setOperator(null); } if (constraintValue() != BaseSingleFieldConstraint.TYPE_LITERAL) { editingCol().setBinding(null); } } boolean isValid() { if (nil(editingCol().getHeader())) { showError(translate(GuidedDecisionTableErraiConstants.ConditionColumnPlugin_YouMustEnterAColumnHeaderValueDescription)); return false; } if (constraintValue() != BaseSingleFieldConstraint.TYPE_PREDICATE) { if (nil(getFactField())) { showError(translate(GuidedDecisionTableErraiConstants.ConditionColumnPlugin_PleaseSelectOrEnterField)); return false; } if (nil(editingCol().getOperator())) { showError(translate(GuidedDecisionTableErraiConstants.ConditionColumnPlugin_NotifyNoSelectedOperator)); return false; } } if (isBindingNotUnique()) { showError(translate(GuidedDecisionTableErraiConstants.ConditionColumnPlugin_PleaseEnterANameThatIsNotAlreadyUsedByAnotherPattern)); return false; } if (isHeaderNotUnique()) { showError(translate(GuidedDecisionTableErraiConstants.ConditionColumnPlugin_ThatColumnNameIsAlreadyInUsePleasePickAnother)); return false; } return true; } @Override public PatternWrapper patternWrapper() { return Optional.ofNullable(patternWrapper).orElse(new PatternWrapper()); } @Override public void setEditingPattern(final PatternWrapper patternWrapper) { this.patternWrapper = patternWrapper; this.editingPattern = extractEditingPattern(); setupDefaultValues(); fireChangeEvent(patternPage); fireChangeEvent(calculationTypePage); fireChangeEvent(fieldPage); fireChangeEvent(operatorPage); fireChangeEvent(valueOptionsPage); fireChangeEvent(additionalInfoPage); } @Override public String getEntryPointName() { return patternWrapper().getEntryPointName(); } @Override public void setEntryPointName(final String entryPointName) { patternWrapper().setEntryPointName(entryPointName); } @Override public List<PatternWrapper> getPatterns() { final Set<PatternWrapper> patterns = new HashSet<>(); for (Pattern52 pattern52 : model().getPatterns()) { patterns.add(new PatternWrapper(pattern52)); } return new ArrayList<>(patterns); } @Override public ConditionCol52 editingCol() { if (nil(patternWrapper().getFactType())) { resetFieldAndOperator(); } return editingCol; } @Override public String getHeader() { return editingCol().getHeader(); } @Override public void setHeader(final String header) { editingCol().setHeader(header); fireChangeEvent(additionalInfoPage); } @Override public void setInsertLogical(Boolean value) { // empty - this widget is not enabled } @Override public void setUpdate(Boolean value) { // empty - this widget is not enabled } @Override public boolean showUpdateEngineWithChanges() { return false; } @Override public boolean showLogicallyInsert() { return false; } @Override public String getFactField() { return editingCol().getFactField(); } @Override public void setFactField(final String selectedValue) { final AsyncPackageDataModelOracle oracle = presenter.getDataModelOracle(); editingCol().setFactField(selectedValue); editingCol().setFieldType(oracle.getFieldType(getFactType(), getFactField())); fireChangeEvent(fieldPage); fireChangeEvent(operatorPage); fireChangeEvent(additionalInfoPage); fireChangeEvent(valueOptionsPage); } @Override public String getBinding() { return editingCol().getBinding(); } @Override public void setBinding(final String binding) { editingCol().setBinding(binding); } @Override public boolean doesOperatorNeedValue() { return validator().doesOperatorNeedValue(editingCol()); } public int constraintValue() { final boolean factHasEnums = presenter.getDataModelOracle().hasEnums(getFactType(), getFactField()); if (factHasEnums) { setConstraintValueFieldAndUpdateEditingCol(BaseSingleFieldConstraint.TYPE_LITERAL); } return constraintValue; } @Override public FieldAccessorsAndMutators getAccessor() { return FieldAccessorsAndMutators.ACCESSOR; } @Override public boolean filterEnumFields() { return constraintValue() == BaseSingleFieldConstraint.TYPE_RET_VALUE; } @Override public GuidedDecisionTable52.TableFormat tableFormat() { return model().getTableFormat(); } @Override public String getValueList() { return editingCol().getValueList(); } public void setValueList(final String valueList) { editingCol().setValueList(valueList); assertDefaultValue(); fireChangeEvent(valueOptionsPage); } @Override public boolean doesOperatorAcceptValueList() { return validator().doesOperatorAcceptValueList(editingCol()); } @Override public IsWidget defaultValueWidget() { return new DefaultWidgetFactory<>(this).create(); } @Override public IsWidget limitedValueWidget() { return new LimitedWidgetFactory<>(this).create(); } private Validator validator() { return new Validator(model().getConditions()); } public void setConstraintValue(final int constraintValue) { setConstraintValueFieldAndUpdateEditingCol(constraintValue); resetFieldAndOperator(); fireChangeEvent(calculationTypePage); fireChangeEvent(fieldPage); fireChangeEvent(operatorPage); } public void setValueOptionsPageAsCompleted() { if (!isValueOptionsPageCompleted()) { setValueOptionsPageCompleted(); fireChangeEvent(valueOptionsPage); } } public Boolean isValueOptionsPageCompleted() { return valueOptionsPageCompleted; } public String getFactType() { return patternWrapper().getFactType(); } public void setOperator(final String operator) { editingCol().setOperator(operator); fireChangeEvent(operatorPage); fireChangeEvent(additionalInfoPage); fireChangeEvent(valueOptionsPage); } void setValueOptionsPageCompleted() { this.valueOptionsPageCompleted = Boolean.TRUE; } boolean isHeaderNotUnique() { return !unique(editingCol().getHeader()); } void showError(final String message) { Window.alert(message); } boolean isBindingNotUnique() { final String binding = editingCol().getBinding(); final BRLRuleModel rm = new BRLRuleModel(model()); return editingCol().isBound() && rm.isVariableNameUsed(binding); } void setupDefaultValues() { editingPattern = emptyPattern(); editingCol = newConditionColumn(); constraintValue = BaseSingleFieldConstraint.TYPE_UNDEFINED; valueOptionsPageCompleted = Boolean.FALSE; } void resetFieldAndOperator() { editingCol.setFactField(""); editingCol.setFieldType(""); editingCol.setOperator(""); } void setConstraintValueFieldAndUpdateEditingCol(int constraintValue) { this.constraintValue = constraintValue; editingCol().setConstraintValueType(constraintValue); } void assertDefaultValue() { final CellUtilities cellUtilities = new CellUtilities(); final AsyncPackageDataModelOracle oracle = presenter.getDataModelOracle(); final ColumnUtilities columnUtilities = new ColumnUtilities(model(), oracle); final List<String> valueList = Arrays.asList(columnUtilities.getValueList(editingCol)); if (valueList.size() > 0) { final String defaultValue = cellUtilities.asString(editingCol().getDefaultValue()); if (!valueList.contains(defaultValue)) { editingCol.getDefaultValue().clearValues(); } } else { //Ensure the Default Value has been updated to represent the column's data-type. final DTCellValue52 defaultValue = editingCol().getDefaultValue(); final DataType.DataTypes dataType = columnUtilities.getDataType(editingPattern(), editingCol()); cellUtilities.convertDTCellValueType(dataType, defaultValue); } } private AdditionalInfoPage initializedAdditionalInfoPage() { return AdditionalInfoPageInitializer.init(additionalInfoPage, this); } private ValueOptionsPage<ConditionColumnPlugin> initializedValueOptionsPage() { return ValueOptionsPageInitializer.init(valueOptionsPage, this); } private boolean unique(String header) { for (CompositeColumn<?> cc : model().getConditions()) { for (int iChild = 0; iChild < cc.getChildColumns().size(); iChild++) { if (cc.getChildColumns().get(iChild).getHeader().equals(header)) { return false; } } } return true; } private ConditionCol52 newConditionColumn() { switch (tableFormat()) { case EXTENDED_ENTRY: return new ConditionCol52(); case LIMITED_ENTRY: return new LimitedEntryConditionCol52(); default: throw new UnsupportedOperationException("Unsupported table format: " + tableFormat()); } } private boolean isExtendedEntryTable() { return tableFormat() == GuidedDecisionTable52.TableFormat.EXTENDED_ENTRY; } GuidedDecisionTable52 model() { return presenter.getModel(); } private Pattern52 emptyPattern() { return new Pattern52().clonePattern(); } }