/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.foundation.bindings; import java.util.Vector; import java.util.logging.Logger; import org.openflexo.foundation.CodeType; import org.openflexo.foundation.FlexoModelObject; import org.openflexo.foundation.TargetType; import org.openflexo.foundation.dm.ComponentDMEntity; import org.openflexo.foundation.dm.DMEntity; import org.openflexo.foundation.dm.DMProperty; import org.openflexo.foundation.dm.DMPropertyImplementationType; import org.openflexo.foundation.dm.DMType; import org.openflexo.foundation.ie.IEObject; import org.openflexo.foundation.ie.operator.ConditionalOperator; import org.openflexo.foundation.ie.widget.IEWidget; import org.openflexo.foundation.param.ChoiceListParameter; import org.openflexo.foundation.param.DMEntityParameter; import org.openflexo.foundation.param.ParameterDefinition; import org.openflexo.foundation.param.TextFieldParameter; import org.openflexo.foundation.validation.FixProposal; import org.openflexo.foundation.validation.ParameteredFixProposal; import org.openflexo.foundation.validation.ValidationError; import org.openflexo.foundation.validation.ValidationIssue; import org.openflexo.foundation.validation.ValidationRule; import org.openflexo.localization.FlexoLocalization; public class RequiredBindingValidationRule<T extends IEObject> extends ValidationRule<RequiredBindingValidationRule<T>, T> { private static final Logger logger = Logger.getLogger(RequiredBindingValidationRule.class.getPackage().getName()); public String bindingName; public String bindingDefinition; public RequiredBindingValidationRule(Class<T> objectType, String aBindingName, String aBindingDefinition) { super(objectType, "binding_must_be_defined"); this.bindingName = aBindingName; this.bindingDefinition = aBindingDefinition; } @Override public String getLocalizedName() { if (bindingName != null) { return FlexoLocalization.localizedForKeyWithParams("binding_named_($bindingName)_is_required", this); } return null; } public String getLocalizedErrorMessageForUndefinedValue() { return FlexoLocalization.localizedForKeyWithParams("binding_named_($bindingName)_is_not_defined", this); } public String getLocalizedErrorMessageForInvalidValue() { return FlexoLocalization.localizedForKeyWithParams("binding_named_($bindingName)_has_invalid_value", this); } @Override public ValidationIssue<RequiredBindingValidationRule<T>, T> applyValidation(final T object) { final FlexoModelObject validatedObject = object; BindingDefinition bd = (BindingDefinition) validatedObject.objectForKey(bindingDefinition); AbstractBinding bv = (AbstractBinding) validatedObject.objectForKey(bindingName); if (bd == null) { logger.warning("Object of type " + object.getClass().getName() + " does not define any '" + bindingDefinition + "' binding definition"); return null; } else if (bd.getIsMandatory()) { if (bv == null || !bv.isBindingValid()) { ValidationError<RequiredBindingValidationRule<T>, T> error; if (bv == null) { error = new ValidationError<RequiredBindingValidationRule<T>, T>(this, object, null) { @Override public String getLocalizedMessage() { return getLocalizedErrorMessageForUndefinedValue(); } }; } else { // !bv.isBindingValid() error = new ValidationError<RequiredBindingValidationRule<T>, T>(this, object, null) { @Override public String getLocalizedMessage() { return getLocalizedErrorMessageForInvalidValue(); } }; } if (object instanceof IEWidget) { error.addToFixProposals(new AddEntryToComponentAndSetBinding(bindingName, bd)); } Vector allAvailableBV = bd.searchMatchingBindingValue((Bindable) validatedObject, 2); for (int i = 0; i < allAvailableBV.size(); i++) { BindingValue proposal = (BindingValue) allAvailableBV.elementAt(i); error.addToFixProposals(new SetBinding(proposal)); } return error; } return null; } return null; } public class SetBinding extends FixProposal<RequiredBindingValidationRule<T>, T> { public BindingValue bindingValue; public SetBinding(BindingValue aBindingValue) { super("set_binding_($bindingName)_to_($bindingValue.stringRepresentation)"); bindingValue = aBindingValue; } @Override protected void fixAction() { ((FlexoModelObject) getObject()).setObjectForKey(bindingValue, bindingName); } public String getBindingName() { return bindingName; } public void setBindingName() { } } protected static ParameterDefinition[] buildParameters(BindingDefinition bd) { ParameterDefinition[] returned = new ParameterDefinition[3]; returned[0] = new TextFieldParameter("variableName", "variable_name", ""); returned[1] = new DMEntityParameter("variableType", "variable_type", bd.getType().getBaseEntity()); returned[2] = new ChoiceListParameter<DMPropertyImplementationType>("implementationType", "implementation_type", DMPropertyImplementationType.PUBLIC_FIELD); returned[2].addParameter("format", "localizedName"); return returned; } public class AddEntryToComponentAndSetBinding extends ParameteredFixProposal<RequiredBindingValidationRule<T>, T> { public BindingDefinition bindingDefinition; public String bindingName; public AddEntryToComponentAndSetBinding(String bindingName, BindingDefinition bd) { super("add_entry_and_set_($bindingName)_onto", buildParameters(bd)); this.bindingName = bindingName; this.bindingDefinition = bd; } @Override protected void fixAction() { String newVariableName = (String) getValueForParameter("variableName"); DMEntity newVariableType = (DMEntity) getValueForParameter("variableType"); DMPropertyImplementationType implementationType = (DMPropertyImplementationType) getValueForParameter("implementationType"); ((IEWidget) getObject()).createsBindingVariable(newVariableName, DMType.makeResolvedDMType(newVariableType), implementationType, false); DMProperty property = null; ComponentDMEntity componentDMEntity = ((IEWidget) getObject()).getComponentDMEntity(); if (componentDMEntity != null) { property = componentDMEntity.getDMProperty(newVariableName); } if (property != null) { BindingVariable var = ((IEWidget) getObject()).getBindingModel().bindingVariableNamed("component"); BindingValue newBindingValue = new BindingValue(bindingDefinition, getObject()); newBindingValue.setBindingVariable(var); newBindingValue.addBindingPathElement(property); newBindingValue.connect(); ((FlexoModelObject) getObject()).setObjectForKey(newBindingValue, bindingName); } } } /** * Overrides isValidForTarget * * @see org.openflexo.foundation.validation.ValidationRule#isValidForTarget(TargetType) */ @Override public boolean isValidForTarget(TargetType targetType) { return getObjectType() == ConditionalOperator.class || targetType != CodeType.PROTOTYPE; } }