Commit 22e6ded4 authored by Romain Bioteau's avatar Romain Bioteau Committed by Adrien

feat(contract) associate contract input with data reference (#1576)

* feat(contract) add matching algo

Closes BST-83
parent 59b2517d
......@@ -160,6 +160,7 @@
containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="inputs" upperBound="-1"
eType="#//ContractInput" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EAttribute" name="dataReference" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="ContractConstraint">
<eStructuralFeatures xsi:type="ecore:EAttribute" name="expression" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
......
<?xml version="1.0" encoding="UTF-8"?>
<genmodel:GenModel xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
xmlns:genmodel="http://www.eclipse.org/emf/2002/GenModel" copyrightText="Copyright (C) 2009-2015 BonitaSoft S.A.&#xD;&#xA;BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble&#xD;&#xA;&#xD;&#xA;This program is free software: you can redistribute it and/or modify&#xD;&#xA;it under the terms of the GNU General Public License as published by&#xD;&#xA;the Free Software Foundation, either version 2.0 of the License, or&#xD;&#xA;(at your option) any later version.&#xD;&#xA;&#xD;&#xA;This program is distributed in the hope that it will be useful,&#xD;&#xA;but WITHOUT ANY WARRANTY; without even the implied warranty of&#xD;&#xA;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the&#xD;&#xA;GNU General Public License for more details.&#xD;&#xA;&#xD;&#xA;You should have received a copy of the GNU General Public License&#xD;&#xA;along with this program. If not, see &lt;http://www.gnu.org/licenses/>."
xmlns:genmodel="http://www.eclipse.org/emf/2002/GenModel" copyrightText="Copyright (C) 2009-2019 BonitaSoft S.A.&#xD;&#xA;BonitaSoft, 32 rue Gustave Eiffel - 38000 Grenoble&#xD;&#xA;&#xD;&#xA;This program is free software: you can redistribute it and/or modify&#xD;&#xA;it under the terms of the GNU General Public License as published by&#xD;&#xA;the Free Software Foundation, either version 2.0 of the License, or&#xD;&#xA;(at your option) any later version.&#xD;&#xA;&#xD;&#xA;This program is distributed in the hope that it will be useful,&#xD;&#xA;but WITHOUT ANY WARRANTY; without even the implied warranty of&#xD;&#xA;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the&#xD;&#xA;GNU General Public License for more details.&#xD;&#xA;&#xD;&#xA;You should have received a copy of the GNU General Public License&#xD;&#xA;along with this program. If not, see &lt;http://www.gnu.org/licenses/>."
modelDirectory="/org.bonitasoft.studio.model/src" editDirectory="/org.bonitasoft.studio.model.edit/src"
modelPluginID="org.bonitasoft.studio.model" templateDirectory="org.bonitasoft.studio-models/EMFTemplates/"
dynamicTemplates="true" redirection="" forceOverwrite="true" modelName="Process"
......@@ -115,8 +115,8 @@
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute expression.ecore#//Expression/returnTypeFixed"/>
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute expression.ecore#//Expression/automaticDependencies"/>
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute expression.ecore#//Expression/htmlAllowed"/>
<genOperations ecoreOperation="expression.ecore#//Expression/hasContent"/>
<genOperations ecoreOperation="expression.ecore#//Expression/hasName"/>
<genOperations ecoreOperation="expression.ecore#//Expression/hasContent" body="return content != null &amp;&amp; !content.isEmpty();"/>
<genOperations ecoreOperation="expression.ecore#//Expression/hasName" body="return name != null &amp;&amp; !name.isEmpty();"/>
</genClasses>
<genClasses ecoreClass="expression.ecore#//ListExpression">
<genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference expression.ecore#//ListExpression/expressions"/>
......@@ -348,7 +348,8 @@
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute process.ecore#//ContractInput/multiple"/>
<genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference process.ecore#//ContractInput/mapping"/>
<genFeatures property="None" children="true" createChild="true" ecoreFeature="ecore:EReference process.ecore#//ContractInput/inputs"/>
<genOperations ecoreOperation="process.ecore#//ContractInput/getJavaType"/>
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute process.ecore#//ContractInput/dataReference"/>
<genOperations ecoreOperation="process.ecore#//ContractInput/getJavaType" body="switch(getType()){&#xD;&#xA;case BOOLEAN:return java.lang.Boolean.class.getName();&#xD;&#xA;case DATE: return java.util.Date.class.getName();&#xD;&#xA;case LOCALDATE: return java.time.LocalDate.class.getName();&#xD;&#xA;case LOCALDATETIME: return java.time.LocalDateTime.class.getName();&#xD;&#xA;case OFFSETDATETIME: return java.time.OffsetDateTime.class.getName();&#xD;&#xA;case INTEGER: return java.lang.Integer.class.getName();&#xA;case LONG: return java.lang.Long.class.getName();&#xD;&#xA;case DECIMAL: return java.lang.Double.class.getName();&#xD;&#xA;case FILE:return &quot;org.bonitasoft.engine.bpm.contract.FileInputValue&quot;;&#xD;&#xA;case COMPLEX:return java.util.Map.class.getName();&#xD;&#xA;case TEXT:&#xD;&#xA;default: return java.lang.String.class.getName();&#xD;&#xA;}"/>
</genClasses>
<genClasses ecoreClass="process.ecore#//ContractConstraint">
<genFeatures createChild="false" ecoreFeature="ecore:EAttribute process.ecore#//ContractConstraint/expression"/>
......
......@@ -14689,5 +14689,50 @@
<releases xmi:id="_z5RnUKwvEeiFZ5S8g2gj5Q" date="2018-08-30T11:43:27.494+0200" label="7.8.0-002">
<changes xsi:type="history:MigrationChange" xmi:id="_z5RnUawvEeiFZ5S8g2gj5Q" migration="org.bonitasoft.studio.migration.custom.migration.connector.UpdateRestConnectorVersionTo106"/>
</releases>
<releases xmi:id="_lGPssDBZEemIIINmMdyzoA" date="2019-02-14T10:43:27.494+0100" label="7.9.0-001">
<changes xsi:type="history:OperationChange" xmi:id="_p10aMDBZEemIIINmMdyzoA">
<changes xsi:type="history:Create" xmi:id="_p10aMTBZEemIIINmMdyzoA" referenceName="eStructuralFeatures">
<target href="process.ecore#//ContractInput"/>
<element href="process.ecore#//ContractInput/dataReference"/>
<changes xsi:type="history:Set" xmi:id="_p10aMjBZEemIIINmMdyzoA" featureName="name" dataValue="dataReference">
<element href="process.ecore#//ContractInput/dataReference"/>
</changes>
<changes xsi:type="history:Set" xmi:id="_p10aMzBZEemIIINmMdyzoA" featureName="eType">
<element href="process.ecore#//ContractInput/dataReference"/>
<referenceValue href="http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</changes>
</changes>
<operation xmi:id="_p10aNDBZEemIIINmMdyzoA" name="newAttribute">
<parameters xmi:id="_p10aNTBZEemIIINmMdyzoA" name="eClass">
<referenceValue xmi:id="_p10aNjBZEemIIINmMdyzoA">
<element href="process.ecore#//ContractInput"/>
</referenceValue>
<referenceValue xmi:id="_p10aNzBZEemIIINmMdyzoA">
<element href="process.ecore#//ContractInput"/>
</referenceValue>
</parameters>
<parameters xmi:id="_p10aODBZEemIIINmMdyzoA" name="name">
<dataValue>dataReference</dataValue>
</parameters>
<parameters xmi:id="_p10aOTBZEemIIINmMdyzoA" name="type">
<referenceValue xmi:id="_p10aOjBZEemIIINmMdyzoA">
<element href="http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</referenceValue>
<referenceValue xmi:id="_p10aOzBZEemIIINmMdyzoA">
<element href="http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</referenceValue>
</parameters>
<parameters xmi:id="_p10aPDBZEemIIINmMdyzoA" name="lowerBound">
<dataValue>0</dataValue>
</parameters>
<parameters xmi:id="_p10aPTBZEemIIINmMdyzoA" name="upperBound">
<dataValue>1</dataValue>
</parameters>
<parameters xmi:id="_p10aPjBZEemIIINmMdyzoA" name="defaultValue">
<dataValue xsi:nil="true"/>
</parameters>
</operation>
</changes>
</releases>
<releases xmi:id="_15TmyGnREeaTLbmqFFisdA"/>
</history:History>
......@@ -176,7 +176,7 @@ public class DeployBDMOperation implements IRunnableWithProgress {
}
protected IEventBroker eventBroker() {
return (IEventBroker) PlatformUI.getWorkbench().getService(IEventBroker.class);
return PlatformUI.getWorkbench().getService(IEventBroker.class);
}
protected void removeDependency() {
......
......@@ -347,7 +347,7 @@ public class AttributesTabItemControl extends AbstractTabItemControl {
final Composite lazyRadioComposite = new Composite(composite, SWT.NONE);
lazyRadioComposite.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create());
lazyRadioComposite.setLayout(GridLayoutFactory.fillDefaults().numColumns(2).margins(0, 0).spacing(25, 0).create());
lazyRadioComposite.setLayout(GridLayoutFactory.fillDefaults().numColumns(1).margins(0, 0).create());
final Button lazyRadio = new Button(lazyRadioComposite, SWT.RADIO);
lazyRadio.setLayoutData(GridDataFactory.swtDefaults().grab(false, false).create());
......@@ -356,7 +356,6 @@ public class AttributesTabItemControl extends AbstractTabItemControl {
final ControlDecoration lazyDecorator = new ControlDecoration(lazyRadio, SWT.RIGHT);
lazyDecorator.setImage(Pics.getImage(PicsConstants.hint));
lazyDecorator.setDescriptionText(Messages.loadOnDemandHint);
lazyDecorator.setMarginWidth(-5);
final Button eagerRadio = new Button(lazyRadioComposite, SWT.RADIO);
eagerRadio.setLayoutData(GridDataFactory.swtDefaults().grab(false, false).create());
......@@ -364,7 +363,6 @@ public class AttributesTabItemControl extends AbstractTabItemControl {
final ControlDecoration eagerDecorator = new ControlDecoration(eagerRadio, SWT.RIGHT);
eagerDecorator.setImage(Pics.getImage(PicsConstants.hint));
eagerDecorator.setMarginWidth(-5);
viewerObservableValue.addValueChangeListener(new IValueChangeListener() {
@Override
......
......@@ -147,16 +147,17 @@ public class ExpressionHelper {
return createSearchIndexDependency(dependency);
}
if (dependency instanceof ContractInput) {
return createContractInputependency(dependency);
return createContractInputDependency(dependency);
}
return EcoreUtil.copy(dependency);
}
private static EObject createContractInputependency(EObject dependency) {
private static EObject createContractInputDependency(EObject dependency) {
final ContractInput contractInputDependency = (ContractInput) EcoreUtil.copy(dependency);
if (contractInputDependency.getType() == ContractInputType.COMPLEX) {
contractInputDependency.getInputs().clear();
}
contractInputDependency.setDataReference(null);
return contractInputDependency;
}
......
......@@ -58,7 +58,18 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="3.9.0",
org.bonitasoft.studio.businessobject,
org.bonitasoft.studio.document,
org.bonitasoft.studio.ui;bundle-version="7.6.0",
org.eclipse.core.databinding.property;bundle-version="1.6.100"
org.eclipse.core.databinding.property;bundle-version="1.6.100",
org.restlet.ext.jackson;bundle-version="2.2.3",
com.fasterxml.jackson.core.jackson-annotations;bundle-version="2.4.4",
com.fasterxml.jackson.core.jackson-core;bundle-version="2.4.4",
com.fasterxml.jackson.core.jackson-databind;bundle-version="2.4.4",
com.fasterxml.jackson.dataformat.jackson-dataformat-csv;bundle-version="2.4.4",
com.fasterxml.jackson.dataformat.jackson-dataformat-smile;bundle-version="2.4.4",
com.fasterxml.jackson.dataformat.jackson-dataformat-xml;bundle-version="2.4.4",
com.fasterxml.jackson.dataformat.jackson-dataformat-yaml;bundle-version="2.4.4",
com.fasterxml.jackson.module.jackson-module-jaxb-annotations;bundle-version="2.4.4",
org.restlet;bundle-version="2.3.0",
org.json;bundle-version="1.0.0"
Bundle-Activator: org.bonitasoft.studio.contract.ContractPlugin
Bundle-ActivationPolicy: lazy
Export-Package: org.bonitasoft.studio.contract.core,
......
......@@ -98,3 +98,4 @@ creatingMappingOperation=Creating mapping operation for %s
saving=Saving...
taskBdmTips=You can first define <a>business variables</a> and/or <a>documents</a>, and then click on "Add from data...".\nIt will automatically map contract inputs to data, and create operations to update data with contract values.
poolBdmTips=You can first define <a>business variables</a> and/or <a>documents</a>, and then click on "Add from data...".\nIt will automatically map contract inputs to data, and initialize data with contract values.
creatingNewForm=Creating new form...
\ No newline at end of file
......@@ -64,6 +64,11 @@
class="org.bonitasoft.studio.contract.core.TaskContractEngineDefinitionBuilder">
</EngineDefinitionBuilder>
</extension>
<extension
point="org.bonitasoft.studio.designer.formOperationFactory">
<factory
class="org.bonitasoft.studio.contract.core.operation.NewFormFromContractOperationFactory"></factory>
</extension>
</plugin>
package org.bonitasoft.studio.contract.core.mapping.treeMaching;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
import static org.bonitasoft.studio.model.businessObject.BusinessObjectBuilder.aBO;
import static org.bonitasoft.studio.model.process.builders.ContractInputBuilder.aContractInput;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.bonitasoft.engine.bdm.model.field.RelationField;
import org.bonitasoft.studio.model.businessObject.FieldBuilder.RelationFieldBuilder;
import org.bonitasoft.studio.model.businessObject.FieldBuilder.SimpleFieldBuilder;
import org.bonitasoft.studio.model.process.BusinessObjectData;
import org.bonitasoft.studio.model.process.Contract;
import org.bonitasoft.studio.model.process.ContractInputType;
import org.bonitasoft.studio.model.process.ProcessFactory;
import org.bonitasoft.studio.model.process.builders.ContractBuilder;
import org.junit.Before;
import org.junit.Test;
public class TreeBuilderTest {
private BusinessDataStore store;
private List<BusinessObjectData> businessData = new ArrayList<>();
@Before
public void setUp() {
store = mock(BusinessDataStore.class);
businessData.add(aData("myData", "org.test.Employee"));
when(store.getBusinessData()).thenReturn(businessData);
RelationField addressField = RelationFieldBuilder.aCompositionField("address", aBO("org.test.Address")
.withField(SimpleFieldBuilder.aStringField("street").build())
.build());
addressField.setCollection(true);
when(store.getBusinessObject("org.test.Employee")).thenReturn(Optional.of(aBO("org.test.Employee")
.withField(SimpleFieldBuilder.aStringField("firstName").build())
.withField(SimpleFieldBuilder.aDateOnlyField("birthDate").build())
.withField(addressField)
.build()));
}
@Test
public void should_build_tree() throws Exception {
TreeBuilder treeBuilder = new TreeBuilder(store);
Contract contract = createMatchingContract();
TreeNode node = treeBuilder.buildBusinessObjectTree(businessData.get(0), contract.getInputs().get(0));
assertThat(node.getInput().getName()).isEqualTo("myDataInput");
assertThat(node.getRef().getName()).isEqualTo("myData");
assertThat(node.getChildren()).extracting("input.name", "ref.name").contains(tuple("address", "address"));
assertThat(node.getChildren().get(0).getChildren()).isEmpty();
}
@SuppressWarnings("unchecked")
private Contract createMatchingContract() {
return ContractBuilder.aContract()
.havingInput(aContractInput()
.withName("myDataInput")
.withType(ContractInputType.COMPLEX)
.havingInput(aContractInput().withName("firstName").withType(ContractInputType.TEXT),
aContractInput().withName("birthDate").withType(ContractInputType.LOCALDATE),
aContractInput().withName("address").withType(ContractInputType.COMPLEX)
.havingInput(aContractInput().withName("street").withType(ContractInputType.TEXT),
aContractInput().withName("city").withType(ContractInputType.TEXT))))
.build();
}
private BusinessObjectData aData(String name, String type) {
BusinessObjectData data = ProcessFactory.eINSTANCE.createBusinessObjectData();
data.setName(name);
data.setClassName(type);
return data;
}
}
/**
* Copyright (C) 2019 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.contract.core.mapping.treeMaching.resolver;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.bonitasoft.studio.contract.core.mapping.treeMaching.BusinessDataStore;
import org.bonitasoft.studio.model.process.BusinessObjectData;
import org.bonitasoft.studio.model.process.ProcessFactory;
import org.bonitasoft.studio.model.process.builders.ContractInputBuilder;
import org.junit.Before;
import org.junit.Test;