Skip to content

Commit

Permalink
FIPS-11962/FIPS-11971 :: Add base class for renamed attribute migrations
Browse files Browse the repository at this point in the history
Change-Id: Ia154aa69874d72b59f7f5419a6a480938f8db704
  • Loading branch information
hd42 committed Oct 2, 2024
1 parent 562ac6a commit 3d5d3b2
Show file tree
Hide file tree
Showing 4 changed files with 330 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*******************************************************************************
* Copyright (c) Faktor Zehn GmbH - faktorzehn.org
*
* This source code is available under the terms of the AGPL Affero General Public License version
* 3.
*
* Please see LICENSE.txt for full license terms, including the additional permissions and
* restrictions as well as the possibility of alternative license terms.
*******************************************************************************/

package org.faktorips.devtools.core.internal.migrationextensions;

import java.util.Arrays;
import java.util.List;

import org.faktorips.devtools.abstraction.exception.IpsException;
import org.faktorips.devtools.core.internal.migration.DefaultMigration;
import org.faktorips.devtools.model.ipsobject.IIpsSrcFile;
import org.faktorips.devtools.model.ipsobject.IpsObjectType;
import org.faktorips.devtools.model.ipsproject.IIpsProject;
import org.faktorips.devtools.model.pctype.IPolicyCmptType;
import org.faktorips.devtools.model.productcmpt.IAttributeValue;
import org.faktorips.devtools.model.productcmpt.IConfigElement;
import org.faktorips.devtools.model.productcmpt.IProductCmpt;
import org.faktorips.devtools.model.productcmpt.IPropertyValue;
import org.faktorips.devtools.model.productcmpttype.IProductCmptType;

/**
* Base class for custom migrations that migrate {@link IProductCmpt product components} after an
* attribute was renamed in a model type.
*/
public class MigrationForChangedAttribute extends DefaultMigration {

private String targetVersion;
private String description;
private ChangedAttribute[] changedAttributes;

public MigrationForChangedAttribute(IIpsProject projectToMigrate, String featureId, String targetVersion,
String description, ChangedAttribute... changedAttributes) {
super(projectToMigrate, featureId);
this.targetVersion = targetVersion;
this.description = description;
this.changedAttributes = changedAttributes;
}

@Override
protected void migrate(IIpsSrcFile srcFile) throws IpsException {
if (IpsObjectType.PRODUCT_CMPT.equals(srcFile.getIpsObjectType())) {
IProductCmpt productCmpt = (IProductCmpt)srcFile.getIpsObject();
IProductCmptType productCmptType = productCmpt.findProductCmptType(getIpsProject());
List<IProductCmptType> productCmptTypes = productCmptType.getSupertypeHierarchy()
.getAllSupertypesInclSelf(productCmptType).stream().map(IProductCmptType.class::cast).toList();
List<IPolicyCmptType> policyCmptTypes = productCmptTypes.stream()
.filter(IProductCmptType::isConfigurationForPolicyCmptType)
.map(t -> t.findPolicyCmptType(getIpsProject())).toList();
Arrays.stream(changedAttributes).forEach(changedAttribute -> {
if (productCmptTypes.stream()
.anyMatch(t -> t.getQualifiedName().equals(changedAttribute.qualifiedTypeName))) {
IAttributeValue attributeValue = productCmpt.getAttributeValue(changedAttribute.oldName);
if (attributeValue != null) {
attributeValue.setAttribute(changedAttribute.newName);
srcFile.save(null);
}
}
if (policyCmptTypes.stream()
.anyMatch(t -> t.getQualifiedName().equals(changedAttribute.qualifiedTypeName))) {
List<IPropertyValue> propertyValues = productCmpt.getPropertyValues(changedAttribute.oldName);
propertyValues.forEach(v -> {
if (v instanceof IConfigElement configElement) {
configElement.setPolicyCmptTypeAttribute(changedAttribute.newName);
}
});
srcFile.save(null);
}
});
}
}

@Override
public String getTargetVersion() {
return targetVersion;
}

@Override
public String getDescription() {
return description;
}

/**
* A changed attribute is defined by the qualified name of the policy component type or product
* component type it is defined in and the old and new name of the attribute.
*/
public record ChangedAttribute(String qualifiedTypeName, String oldName, String newName) {

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,11 @@ Export-Package: org.faktorips.devtools.model,
org.faktorips.devtools.core.ui,
org.faktorips.devtools.core.ui.test,
org.faktorips.devtools.model.decorators",
org.faktorips.devtools.model.internal.type;x-friends:="org.faktorips.abstracttest,org.faktorips.devtools.core.ui,org.faktorips.devtools.core.ui.test",
org.faktorips.devtools.model.internal.type;
x-friends:="org.faktorips.abstracttest,
org.faktorips.devtools.core.ui,
org.faktorips.devtools.core.ui.test,
org.faktorips.devtools.core.test",
org.faktorips.devtools.model.internal.util;x-friends:="org.faktorips.devtools.core.ui,org.faktorips.devtools.core.ui.test",
org.faktorips.devtools.model.internal.value;x-friends:="org.faktorips.devtools.multiediting,org.faktorips.devtools.multiediting.test",
org.faktorips.devtools.model.internal.valueset;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ Import-Package: org.faktorips.abstracttest,
org.faktorips.devtools.model.internal.productcmpt,
org.faktorips.devtools.model.internal.tablecontents,
org.faktorips.devtools.model.internal.testcasetype,
org.faktorips.devtools.model.internal.type,
org.faktorips.devtools.model.internal.valueset,
org.faktorips.devtools.model.ipsobject,
org.faktorips.devtools.model.ipsproject,
org.faktorips.devtools.model.method,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
/*******************************************************************************
* Copyright (c) Faktor Zehn GmbH - faktorzehn.org
*
* This source code is available under the terms of the AGPL Affero General Public License version
* 3.
*
* Please see LICENSE.txt for full license terms, including the additional permissions and
* restrictions as well as the possibility of alternative license terms.
*******************************************************************************/

package org.faktorips.devtools.core.internal.migrationextensions;

import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.faktorips.abstracttest.AbstractIpsPluginTest;
import org.faktorips.abstracttest.TestIpsModelExtensions;
import org.faktorips.datatype.Datatype;
import org.faktorips.devtools.core.internal.migrationextensions.MigrationForChangedAttribute.ChangedAttribute;
import org.faktorips.devtools.model.internal.pctype.PolicyCmptType;
import org.faktorips.devtools.model.internal.productcmpt.ProductCmpt;
import org.faktorips.devtools.model.internal.productcmpt.SingleValueHolder;
import org.faktorips.devtools.model.internal.productcmpttype.ProductCmptType;
import org.faktorips.devtools.model.ipsproject.IIpsProject;
import org.faktorips.devtools.model.ipsproject.IIpsProjectProperties;
import org.faktorips.devtools.model.pctype.IPolicyCmptTypeAttribute;
import org.faktorips.devtools.model.productcmpt.IAttributeValue;
import org.faktorips.devtools.model.productcmpt.IConfiguredDefault;
import org.faktorips.devtools.model.productcmpt.IConfiguredValueSet;
import org.faktorips.devtools.model.productcmpttype.IProductCmptType;
import org.faktorips.devtools.model.productcmpttype.IProductCmptTypeAttribute;
import org.faktorips.devtools.model.valueset.IStringLengthValueSet;
import org.faktorips.devtools.model.valueset.ValueSetType;
import org.faktorips.devtools.model.versionmanager.IIpsFeatureVersionManager;
import org.junit.Test;

public class MigrationForChangedAttributeTest extends AbstractIpsPluginTest {

private static final String FEATURE_ID = "my.feature";

private IIpsFeatureVersionManager versionManager;

@Override
public void setUp() throws Exception {
super.setUp();
versionManager = mock(IIpsFeatureVersionManager.class);
when(versionManager.getFeatureId()).thenReturn(FEATURE_ID);
when(versionManager.isRequiredForAllProjects()).thenReturn(false);
}

@Test
public void testMigrationOfProductAttribute() {
try (TestIpsModelExtensions testIpsModelExtensions = TestIpsModelExtensions.get()) {
testIpsModelExtensions.setFeatureVersionManagers(versionManager);
IIpsProject ipsProject = newIpsProjectWithFeature();
ProductCmptType changedProductCmptType = newProductCmptType(ipsProject,
"model.products.ChangedProductCmptType");
String oldAttributeName = "oldAttributeName";
IProductCmptTypeAttribute changedAttribute = newAttribute(changedProductCmptType, oldAttributeName);
ProductCmpt productCmpt = newProductCmpt(changedProductCmptType, "productToChange");
setAttributeValue(productCmpt, changedAttribute, "aValue");
changedAttribute.setName("newAttributeName");
changedProductCmptType.getIpsSrcFile().save(null);
MigrationForChangedAttribute migration = new MigrationForChangedAttribute(ipsProject, FEATURE_ID, "2",
"a description", new ChangedAttribute(
"model.products.ChangedProductCmptType", oldAttributeName, "newAttributeName"));

migration.migrate(productCmpt.getIpsSrcFile());

assertThat(productCmpt.getAttributeValue("oldAttributeName"), is(nullValue()));
assertThat(productCmpt.getAttributeValue("newAttributeName").getValueHolder().getStringValue(),
is("aValue"));
}
}

@Test
public void testMigrationOfPolicyAttribute() {
try (TestIpsModelExtensions testIpsModelExtensions = TestIpsModelExtensions.get()) {
testIpsModelExtensions.setFeatureVersionManagers(versionManager);
IIpsProject ipsProject = newIpsProjectWithFeature();
PolicyCmptType changedPolicyCmptType = newPolicyAndProductCmptType(ipsProject,
"model.ChangedPolicyCmptType", "model.ChangedProductCmptType");
IProductCmptType changedProductCmptType = changedPolicyCmptType.findProductCmptType(ipsProject);
String oldAttributeName = "oldAttributeName";
IPolicyCmptTypeAttribute changedAttribute = newAttribute(changedPolicyCmptType, oldAttributeName);
ProductCmpt productCmpt = newProductCmpt(changedProductCmptType, "productToChange");
setDefaultValue(productCmpt, changedAttribute, "aValue");
setValueSetStringLength(productCmpt, changedAttribute, "10");
changedAttribute.setName("newAttributeName");
changedPolicyCmptType.getIpsSrcFile().save(null);
MigrationForChangedAttribute migration = new MigrationForChangedAttribute(ipsProject, FEATURE_ID, "2",
"a description", new ChangedAttribute(
"model.ChangedPolicyCmptType", oldAttributeName, "newAttributeName"));

migration.migrate(productCmpt.getIpsSrcFile());

assertThat(productCmpt.getPropertyValue("oldAttributeName", IConfiguredDefault.class), is(nullValue()));
assertThat(productCmpt.getPropertyValue("newAttributeName", IConfiguredDefault.class).getValue(),
is("aValue"));
assertThat(productCmpt.getPropertyValue("oldAttributeName", IConfiguredValueSet.class), is(nullValue()));
assertThat(productCmpt.getPropertyValue("newAttributeName", IConfiguredValueSet.class).getValueSet(),
is(instanceOf(IStringLengthValueSet.class)));
assertThat(
((IStringLengthValueSet)productCmpt.getPropertyValue("newAttributeName", IConfiguredValueSet.class)
.getValueSet()).getMaximumLength(),
is("10"));
}
}

@Test
public void testMigrationOfSubtype() {
try (TestIpsModelExtensions testIpsModelExtensions = TestIpsModelExtensions.get()) {
testIpsModelExtensions.setFeatureVersionManagers(versionManager);
IIpsProject ipsProject = newIpsProjectWithFeature();
ProductCmptType changedProductCmptType = newProductCmptType(ipsProject,
"model.products.ChangedProductCmptType");
ProductCmptType subProductCmptType = newProductCmptType(ipsProject,
"model.products.SubProductCmptType");
subProductCmptType.setSupertype("model.products.ChangedProductCmptType");
String oldAttributeName = "oldAttributeName";
IProductCmptTypeAttribute changedAttribute = newAttribute(changedProductCmptType, oldAttributeName);
ProductCmpt productCmpt = newProductCmpt(subProductCmptType, "productToChange");
setAttributeValue(productCmpt, changedAttribute, "aValue");
changedAttribute.setName("newAttributeName");
changedProductCmptType.getIpsSrcFile().save(null);
MigrationForChangedAttribute migration = new MigrationForChangedAttribute(ipsProject, FEATURE_ID, "2",
"a description", new ChangedAttribute(
"model.products.ChangedProductCmptType", oldAttributeName, "newAttributeName"));

migration.migrate(productCmpt.getIpsSrcFile());

assertThat(productCmpt.getAttributeValue("oldAttributeName"), is(nullValue()));
assertThat(productCmpt.getAttributeValue("newAttributeName").getValueHolder().getStringValue(),
is("aValue"));
}
}

@Test
public void testMigrationTwice() {
try (TestIpsModelExtensions testIpsModelExtensions = TestIpsModelExtensions.get()) {
testIpsModelExtensions.setFeatureVersionManagers(versionManager);
IIpsProject ipsProject = newIpsProjectWithFeature();
ProductCmptType changedProductCmptType = newProductCmptType(ipsProject,
"model.products.ChangedProductCmptType");
String oldAttributeName = "oldAttributeName";
IProductCmptTypeAttribute changedAttribute = newAttribute(changedProductCmptType, oldAttributeName);
ProductCmpt productCmpt = newProductCmpt(changedProductCmptType, "productToChange");
setAttributeValue(productCmpt, changedAttribute, "aValue");
changedAttribute.setName("newAttributeName");
changedProductCmptType.getIpsSrcFile().save(null);
MigrationForChangedAttribute migration = new MigrationForChangedAttribute(ipsProject, FEATURE_ID, "2",
"a description", new ChangedAttribute(
"model.products.ChangedProductCmptType", oldAttributeName, "newAttributeName"));

migration.migrate(productCmpt.getIpsSrcFile());

assertThat(productCmpt.getAttributeValue("oldAttributeName"), is(nullValue()));
assertThat(productCmpt.getAttributeValue("newAttributeName").getValueHolder().getStringValue(),
is("aValue"));

migration.migrate(productCmpt.getIpsSrcFile());

assertThat(productCmpt.getAttributeValue("oldAttributeName"), is(nullValue()));
assertThat(productCmpt.getAttributeValue("newAttributeName").getValueHolder().getStringValue(),
is("aValue"));
}
}

private void setAttributeValue(ProductCmpt productCmpt,
IProductCmptTypeAttribute changedAttribute,
String value) {
IAttributeValue attributeValue = productCmpt.newPropertyValue(changedAttribute, IAttributeValue.class);
attributeValue.setAttribute(changedAttribute.getName());
attributeValue.setValueHolder(new SingleValueHolder(attributeValue, value));
productCmpt.getIpsSrcFile().save(null);
}

private IProductCmptTypeAttribute newAttribute(ProductCmptType changedProductCmptType, String name) {
IProductCmptTypeAttribute changedAttribute = changedProductCmptType.newProductCmptTypeAttribute(name);
changedAttribute.setDatatype(Datatype.STRING.getQualifiedName());
changedProductCmptType.getIpsSrcFile().save(null);
return changedAttribute;
}

private void setDefaultValue(ProductCmpt productCmpt,
IPolicyCmptTypeAttribute changedAttribute,
String value) {
IConfiguredDefault defaultValue = productCmpt.newPropertyValue(changedAttribute, IConfiguredDefault.class);
defaultValue.setPolicyCmptTypeAttribute(changedAttribute.getName());
defaultValue.setValue(value);
productCmpt.getIpsSrcFile().save(null);
}

private void setValueSetStringLength(ProductCmpt productCmpt,
IPolicyCmptTypeAttribute changedAttribute,
String value) {
IConfiguredValueSet configuredValueSet = productCmpt.newPropertyValue(changedAttribute,
IConfiguredValueSet.class);
configuredValueSet.setPolicyCmptTypeAttribute(changedAttribute.getName());
IStringLengthValueSet valueSet = (IStringLengthValueSet)configuredValueSet
.changeValueSetType(ValueSetType.STRINGLENGTH);
valueSet.setMaximumLength(value);
productCmpt.getIpsSrcFile().save(null);
}

private IPolicyCmptTypeAttribute newAttribute(PolicyCmptType changedPolicyCmptType, String name) {
IPolicyCmptTypeAttribute changedAttribute = changedPolicyCmptType.newPolicyCmptTypeAttribute(name);
changedAttribute.setDatatype(Datatype.STRING.getQualifiedName());
changedAttribute.setValueSetConfiguredByProduct(true);
changedPolicyCmptType.getIpsSrcFile().save(null);
return changedAttribute;
}

private IIpsProject newIpsProjectWithFeature() {
IIpsProject ipsProject = newIpsProject();
IIpsProjectProperties props = ipsProject.getProperties();
props.setMinRequiredVersionNumber(FEATURE_ID, "1");
ipsProject.setProperties(props);
return ipsProject;
}

}

0 comments on commit 3d5d3b2

Please sign in to comment.