Commit a8f59146 authored by Romain Bioteau's avatar Romain Bioteau
Browse files

add validation constraint

parent 716dbd76
......@@ -6,4 +6,5 @@ widgetRepository=Widgets
pageDesigner=Page designer
externalURL=External URL
targetForm=Target form
url=URL
\ No newline at end of file
url=URL
pageDoesntExists=Page '{0}' doesn't exists.
\ No newline at end of file
......@@ -30,6 +30,7 @@ public class Messages extends NLS {
public static String externalURL;
public static String targetForm;
public static String url;
public static String pageDoesntExists;
static {
NLS.initializeMessages("messages", Messages.class);
......
......@@ -18,8 +18,10 @@ import javax.inject.Inject;
import org.bonitasoft.studio.common.jface.databinding.CustomEMFEditObservables;
import org.bonitasoft.studio.common.properties.AbstractBonitaDescriptionSection;
import org.bonitasoft.studio.common.repository.RepositoryAccessor;
import org.bonitasoft.studio.model.process.ProcessPackage;
import org.bonitasoft.studio.pagedesigner.ui.property.section.control.FormMappingRadioGroup;
import org.bonitasoft.studio.pagedesigner.ui.property.section.control.FormReferenceExpressionValidator;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.e4.core.di.extensions.Preference;
......@@ -46,11 +48,18 @@ public class EntryFormMappingPropertySection extends AbstractBonitaDescriptionSe
@Preference(nodePath = "org.bonitasoft.studio.preferences")
private IEclipsePreferences preferenceStore;
@Inject
private RepositoryAccessor repositoryAccessor;
@Inject
private FormReferenceExpressionValidator formReferenceExpressionValidator;
@Override
public void createControls(final Composite parent, final TabbedPropertySheetPage aTabbedPropertySheetPage) {
super.createControls(parent, aTabbedPropertySheetPage);
context = new EMFDataBindingContext();
final FormMappingRadioGroup formMappingRadioGroup = new FormMappingRadioGroup(parent, aTabbedPropertySheetPage.getWidgetFactory(), preferenceStore);
final FormMappingRadioGroup formMappingRadioGroup = new FormMappingRadioGroup(parent, aTabbedPropertySheetPage.getWidgetFactory(), preferenceStore,
repositoryAccessor, formReferenceExpressionValidator);
formMappingRadioGroup.doBindControl(context, CustomEMFEditObservables.observeDetailValue(Realm.getDefault(),
ViewersObservables.observeSingleSelection(selectionProvider),
getFormMappingFeature()));
......
......@@ -18,6 +18,7 @@ import static org.bonitasoft.studio.common.jface.databinding.UpdateStrategyFacto
import static org.bonitasoft.studio.common.jface.databinding.UpdateStrategyFactory.updateValueStrategy;
import org.bonitasoft.studio.common.jface.databinding.CustomEMFEditObservables;
import org.bonitasoft.studio.common.repository.RepositoryAccessor;
import org.bonitasoft.studio.model.process.ProcessPackage;
import org.bonitasoft.studio.pagedesigner.i18n.Messages;
import org.bonitasoft.studio.preferences.BonitaPreferenceConstants;
......@@ -47,7 +48,8 @@ public class FormMappingRadioGroup extends Composite implements BonitaPreference
private final URLMappingComposite urlMappingComposite;
private final CustomStackLayout stackLayout;
public FormMappingRadioGroup(final Composite parent, final TabbedPropertySheetWidgetFactory widgetFactory, final IEclipsePreferences preferenceStore) {
public FormMappingRadioGroup(final Composite parent, final TabbedPropertySheetWidgetFactory widgetFactory, final IEclipsePreferences preferenceStore,
final RepositoryAccessor repositoryAccessor, final FormReferenceExpressionValidator formReferenceExpressionValidator) {
super(parent, SWT.NONE);
setLayout(GridLayoutFactory.fillDefaults().numColumns(2).extendedMargins(10, 10, 10, 10).create());
......@@ -66,7 +68,8 @@ public class FormMappingRadioGroup extends Composite implements BonitaPreference
stackLayout = new CustomStackLayout(stackedComposite);
stackedComposite.setLayout(stackLayout);
pageDesignerMappingComposite = new PageDesignerMappingComposite(stackedComposite, widgetFactory, preferenceStore);
pageDesignerMappingComposite = new PageDesignerMappingComposite(stackedComposite, widgetFactory, preferenceStore, repositoryAccessor,
formReferenceExpressionValidator);
urlMappingComposite = new URLMappingComposite(stackedComposite, widgetFactory);
final Object externalValue = externalObservable.getValue();
......
/**
* Copyright (C) 2014 BonitaSoft S.A.
* BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble
* This program 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 2.0 of the License, or
* (at your option) any later version.
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.bonitasoft.studio.pagedesigner.ui.property.section.control;
import javax.inject.Inject;
import org.bonitasoft.studio.common.ExpressionConstants;
import org.bonitasoft.studio.common.repository.RepositoryAccessor;
import org.bonitasoft.studio.expression.editor.provider.IExpressionValidator;
import org.bonitasoft.studio.model.expression.Expression;
import org.bonitasoft.studio.pagedesigner.core.repository.WebPageRepositoryStore;
import org.bonitasoft.studio.pagedesigner.i18n.Messages;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.e4.core.di.annotations.Creatable;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.domain.EditingDomain;
/**
* @author Romain Bioteau
*/
@Creatable
public class FormReferenceExpressionValidator implements IExpressionValidator {
private Expression inputExpression;
@Inject
private RepositoryAccessor repositoryAccessor;
/*
* (non-Javadoc)
* @see org.eclipse.core.databinding.validation.IValidator#validate(java.lang.Object)
*/
@Override
public IStatus validate(final Object value) {
final String content = inputExpression.getContent();
final WebPageRepositoryStore repositoryStore = repositoryAccessor.getRepositoryStore(WebPageRepositoryStore.class);
if (repositoryStore.getChild(String.format("%s.json", content)) == null) {
return ValidationStatus.error(Messages.bind(Messages.pageDoesntExists, String.format("%s -- %s", inputExpression.getName(), content)));
}
return ValidationStatus.ok();
}
/*
* (non-Javadoc)
* @see org.bonitasoft.studio.expression.editor.provider.IExpressionValidator#setInputExpression(org.bonitasoft.studio.model.expression.Expression)
*/
@Override
public void setInputExpression(final Expression inputExpression) {
this.inputExpression = inputExpression;
}
/*
* (non-Javadoc)
* @see org.bonitasoft.studio.expression.editor.provider.IExpressionValidator#setDomain(org.eclipse.emf.edit.domain.EditingDomain)
*/
@Override
public void setDomain(final EditingDomain domain) {
}
/*
* (non-Javadoc)
* @see org.bonitasoft.studio.expression.editor.provider.IExpressionValidator#setContext(org.eclipse.emf.ecore.EObject)
*/
@Override
public void setContext(final EObject context) {
}
/*
* (non-Javadoc)
* @see org.bonitasoft.studio.expression.editor.provider.IExpressionValidator#isRelevantForExpressionType(java.lang.String)
*/
@Override
public boolean isRelevantForExpressionType(final String type) {
return ExpressionConstants.FORM_REFERENCE_TYPE.equals(type);
}
}
......@@ -20,6 +20,7 @@ import org.bonitasoft.studio.browser.operation.OpenBrowserOperation;
import org.bonitasoft.studio.common.ExpressionConstants;
import org.bonitasoft.studio.common.jface.databinding.CustomEMFEditObservables;
import org.bonitasoft.studio.common.log.BonitaStudioLog;
import org.bonitasoft.studio.common.repository.RepositoryAccessor;
import org.bonitasoft.studio.expression.editor.filter.AvailableExpressionTypeFilter;
import org.bonitasoft.studio.expression.editor.viewer.ExpressionViewer;
import org.bonitasoft.studio.model.expression.Expression;
......@@ -54,7 +55,11 @@ public class PageDesignerMappingComposite extends Composite implements BonitaPre
private final ExpressionViewer targetFormExpressionViewer;
private final IEclipsePreferences preferenceStore;
public PageDesignerMappingComposite(final Composite parent, final TabbedPropertySheetWidgetFactory widgetFactory, final IEclipsePreferences preferenceStore) {
public PageDesignerMappingComposite(final Composite parent,
final TabbedPropertySheetWidgetFactory widgetFactory,
final IEclipsePreferences preferenceStore,
final RepositoryAccessor repositoryAccessor,
final FormReferenceExpressionValidator formReferenceExpressionValidator) {
super(parent, SWT.NONE);
this.preferenceStore = preferenceStore;
setLayout(GridLayoutFactory.fillDefaults().numColumns(2).extendedMargins(10, 0, 10, 0).create());
......@@ -64,6 +69,7 @@ public class PageDesignerMappingComposite extends Composite implements BonitaPre
targetFormExpressionViewer = new ExpressionViewer(this, SWT.BORDER, widgetFactory);
targetFormExpressionViewer.getControl().setLayoutData(GridDataFactory.fillDefaults().hint(WIDTH_HINT, SWT.DEFAULT).create());
targetFormExpressionViewer.setExpressionProposalLableProvider(new FormReferenceProposalLabelProvider());
targetFormExpressionViewer.addExpressionValidator(formReferenceExpressionValidator);
targetFormExpressionViewer.addFilter(new AvailableExpressionTypeFilter(new String[] { ExpressionConstants.FORM_REFERENCE_TYPE }));
widgetFactory.adapt(this);
......@@ -86,7 +92,7 @@ public class PageDesignerMappingComposite extends Composite implements BonitaPre
});
}
protected void clearExistingSelectionListeners(final ToolItem editControl) {
private void clearExistingSelectionListeners(final ToolItem editControl) {
final Listener[] toRemove = editControl.getListeners(SWT.Selection);
for (final Listener l : toRemove) {
editControl.removeListener(SWT.Selection, l);
......
......@@ -31,7 +31,8 @@ Require-Bundle: org.eclipse.ui,
org.codehaus.groovy;bundle-version="1.8.6",
org.bonitasoft.studio.condition.ui,
org.bonitasoft.studio.tests-utils;bundle-version="6.4.0";resolution:=optional,
org.bonitasoft.studio.document
org.bonitasoft.studio.document,
org.bonitasoft.studio.pagedesigner;bundle-version="7.0.0"
Bundle-ActivationPolicy: lazy
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
......
......@@ -89,4 +89,7 @@ queryReturnTypeIsInvalid=Query expression {0} return type ({1}) is not the same
queryReferencedAnUnexistingBusinessObject=Query expression {1} referenced {0} Business Object. However, {0} has not been found in the Business Data Model.
queryParameterReturnTypeIsInvalid=Query expression {0} contains a query parameter {1} with an invalid return type ({2}, but expecting {3}).
queryParameterDoesNotExistInQueryDefinition=Query expression {0} contains a query parameter {1} that doesn't exist in query definition.
queryParameterDoesNotExistInExpression=Query parameter {1} is missing for Query expression {0}.
\ No newline at end of file
queryParameterDoesNotExistInExpression=Query parameter {1} is missing for Query expression {0}.
invalidFormMapping=Invalid {0}. {1} doesn't exists.
entryFormMapping=entry form mapping
overviewFormMapping=overview form mapping
\ No newline at end of file
......@@ -984,6 +984,21 @@
class="MultiInstantiable:http://www.bonitasoft.org/ns/studio/process">
</target>
</constraint>
<constraint
class="org.bonitasoft.studio.validation.constraints.process.FormMappingConstraint"
id="org.bonitasoft.studio.validation.constraints.formMapping"
lang="Java"
mode="Batch"
name="Form Mapping constraint"
severity="WARNING"
statusCode="1">
<message>
{0}
</message>
<target
class="FormMapping:http://www.bonitasoft.org/ns/studio/process">
</target>
</constraint>
</constraints>
<package
namespaceUri="http://www.bonitasoft.org/ns/studio/process">
......
/**
* Copyright (C) 2014 BonitaSoft S.A.
* BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble
* This program 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 2.0 of the License, or
* (at your option) any later version.
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.bonitasoft.studio.validation.constraints.process;
import static org.bonitasoft.studio.assertions.StatusAssert.assertThat;
import static org.bonitasoft.studio.model.expression.builders.ExpressionBuilder.anExpression;
import static org.bonitasoft.studio.model.process.builders.FormMappingBuilder.aFormMapping;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doReturn;
import org.bonitasoft.studio.common.repository.RepositoryAccessor;
import org.bonitasoft.studio.pagedesigner.core.repository.WebPageFileStore;
import org.bonitasoft.studio.pagedesigner.core.repository.WebPageRepositoryStore;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.validation.IValidationContext;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;
/**
* @author Romain Bioteau
*/
@RunWith(MockitoJUnitRunner.class)
public class FormMappingConstraintTest {
@Spy
private FormMappingConstraint formMappingConstraint;
@Mock
private IValidationContext ctx;
@Mock
private RepositoryAccessor repositoryAccessor;
@Mock
private WebPageRepositoryStore webPageRepositoryStore;
@Mock
private WebPageFileStore fileStore;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
doReturn(repositoryAccessor).when(formMappingConstraint).getRepositoryAccessor();
doReturn(webPageRepositoryStore).when(repositoryAccessor).getRepositoryStore(WebPageRepositoryStore.class);
doReturn(ValidationStatus.ok()).when(ctx).createSuccessStatus();
doReturn(ValidationStatus.error("error")).when(ctx).createFailureStatus(any(Object.class));
}
@Test
public void should_return_an_error_if_form_doesnt_exists_in_repository() throws Exception {
doReturn(aFormMapping().internal().havingTargetForm(anExpression().withContent("an_id_that_doesnt_esists")).build()).when(ctx).getTarget();
final IStatus status = formMappingConstraint.performBatchValidation(ctx);
assertThat(status).isNotOK();
}
@Test
public void should_return_a_valid_status_if_form_exists_in_repository() throws Exception {
doReturn(aFormMapping().internal().havingTargetForm(anExpression().withContent("an_id_that_esists")).build()).when(ctx).getTarget();
doReturn(fileStore).when(webPageRepositoryStore).getChild("an_id_that_esists.json");
final IStatus status = formMappingConstraint.performBatchValidation(ctx);
assertThat(status).isOK();
}
@Test
public void should_return_a_valid_status_if_no_target_form_on_mapping() throws Exception {
doReturn(aFormMapping().internal().havingTargetForm(anExpression()).build()).when(ctx).getTarget();
final IStatus status = formMappingConstraint.performBatchValidation(ctx);
assertThat(status).isOK();
}
@Test(expected = IllegalArgumentException.class)
public void should_throw_an_IllegalArgumentException_if_target_is_not_a_FormMapping() throws Exception {
doReturn(anExpression().build()).when(ctx).getTarget();
formMappingConstraint.performBatchValidation(ctx);
}
}
/**
* Copyright (C) 2010-2015 BonitaSoft S.A.
* BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble
* This program 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 2.0 of the License, or
* (at your option) any later version.
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.bonitasoft.studio.validation.constraints.process;
import static com.google.common.base.Preconditions.checkArgument;
import org.bonitasoft.studio.common.repository.RepositoryAccessor;
import org.bonitasoft.studio.model.expression.Expression;
import org.bonitasoft.studio.model.process.FormMapping;
import org.bonitasoft.studio.model.process.ProcessPackage;
import org.bonitasoft.studio.model.process.diagram.providers.ProcessMarkerNavigationProvider;
import org.bonitasoft.studio.pagedesigner.core.repository.WebPageRepositoryStore;
import org.bonitasoft.studio.validation.constraints.AbstractLiveValidationMarkerConstraint;
import org.bonitasoft.studio.validation.i18n.Messages;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.validation.IValidationContext;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditor;
/**
* @author Romain Bioteau
*/
public class FormMappingConstraint extends AbstractLiveValidationMarkerConstraint {
public static final String ID = "org.bonitasoft.studio.validation.constraints.formMapping";
@Override
protected IStatus performLiveValidation(final IValidationContext ctx) {
return ctx.createSuccessStatus();
}
@Override
protected String getMarkerType(final DiagramEditor editor) {
return ProcessMarkerNavigationProvider.MARKER_TYPE;
}
@Override
protected String getConstraintId() {
return ID;
}
@Override
protected IStatus performBatchValidation(final IValidationContext ctx) {
final EObject eObj = ctx.getTarget();
checkArgument(eObj instanceof FormMapping);
final FormMapping formMapping = (FormMapping) eObj;
final Expression targetForm = formMapping.getTargetForm();
if (targetForm.hasContent()) {
final RepositoryAccessor repositoryAccessor = getRepositoryAccessor();
final WebPageRepositoryStore repositoryStore = repositoryAccessor.getRepositoryStore(WebPageRepositoryStore.class);
if (repositoryStore.getChild(targetForm.getContent() + ".json") == null) {
return ctx.createFailureStatus(Messages.bind(Messages.invalidFormMapping, mappingKind(eObj), targetForm.getContent() + ".json"));
}
}
return ctx.createSuccessStatus();
}
private String mappingKind(final EObject eObj) {
return eObj.eContainingFeature().equals(ProcessPackage.Literals.PAGE_FLOW__FORM_MAPPING) ? Messages.entryFormMapping : Messages.overviewFormMapping;
}
protected RepositoryAccessor getRepositoryAccessor() {
final RepositoryAccessor repositoryAccessor = new RepositoryAccessor();
repositoryAccessor.init();
return repositoryAccessor;
}
}
......@@ -203,6 +203,12 @@ public class Messages extends NLS {
public static String businessObjectDefinitionNotFound;
public static String invalidFormMapping;
public static String entryFormMapping;
public static String overviewFormMapping;
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment