package com.constellio.model.services.records;
import static com.constellio.model.entities.schemas.MetadataValueType.NUMBER;
import static com.constellio.model.entities.schemas.MetadataValueType.STRING;
import static com.constellio.sdk.tests.schemas.TestsSchemasSetup.whichIsMultivalue;
import static com.constellio.sdk.tests.schemas.TestsSchemasSetup.whichIsReferencing;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.junit.Before;
import org.junit.Test;
import com.constellio.model.entities.calculators.CalculatorParameters;
import com.constellio.model.entities.calculators.DynamicDependencyValues;
import com.constellio.model.entities.calculators.MetadataValueCalculator;
import com.constellio.model.entities.calculators.dependencies.Dependency;
import com.constellio.model.entities.calculators.dependencies.DynamicLocalDependency;
import com.constellio.model.entities.records.Record;
import com.constellio.model.entities.schemas.Metadata;
import com.constellio.model.entities.schemas.MetadataValueType;
import com.constellio.model.services.records.RecordServicesRuntimeException.RecordServicesRuntimeException_CalculatorIsUsingAnForbiddenMetadata;
import com.constellio.model.services.records.RecordServicesRuntimeException.RecordServicesRuntimeException_ExceptionWhileCalculating;
import com.constellio.model.services.schemas.MetadataList;
import com.constellio.model.services.schemas.MetadataSchemaTypesAlteration;
import com.constellio.model.services.schemas.builders.MetadataSchemaBuilderRuntimeException;
import com.constellio.model.services.schemas.builders.MetadataSchemaTypesBuilder;
import com.constellio.sdk.tests.ConstellioTest;
import com.constellio.sdk.tests.TestRecord;
import com.constellio.sdk.tests.schemas.TestsSchemasSetup;
import com.constellio.sdk.tests.schemas.TestsSchemasSetup.AnotherSchemaMetadatas;
import com.constellio.sdk.tests.schemas.TestsSchemasSetup.ThirdSchemaMetadatas;
import com.constellio.sdk.tests.schemas.TestsSchemasSetup.ZeSchemaMetadatas;
public class DynamicDependencyCalculatorAcceptanceTest extends ConstellioTest {
private static AtomicInteger recalculationCounter = new AtomicInteger();
private static LocalDate aDate = new LocalDate(2016, 11, 4);
private static LocalDateTime aDateTime = new LocalDateTime(2016, 11, 4, 1, 2, 3);
private String calculatedMetadata = "calculatedMetadata";
private String anotherCalculatedMetadata = "anotherCalculatedMetadata";
TestsSchemasSetup schemas = new TestsSchemasSetup(zeCollection);
static ZeSchemaMetadatas zeSchema;
static AnotherSchemaMetadatas anotherSchema;
static ThirdSchemaMetadatas thirdSchema;
String anotherSchemaRecordId = "42";
RecordServices recordServices;
@Before
public void setUp()
throws Exception {
defineSchemasManager().using(schemas
.withAStringMetadata()
.withAnotherStringMetadata(whichIsMultivalue)
.withADateMetadata()
.withADateTimeMetadata()
.withABooleanMetadata()
.withAReferenceMetadata(whichIsReferencing("anotherSchemaType")));
zeSchema = schemas.new ZeSchemaMetadatas();
anotherSchema = schemas.new AnotherSchemaMetadatas();
thirdSchema = schemas.new ThirdSchemaMetadatas();
recordServices = getModelLayerFactory().newRecordServices();
recordServices.add(new TestRecord(anotherSchema, anotherSchemaRecordId));
recalculationCounter = new AtomicInteger();
}
@Test
public void givenMetadataCalculatorHasADynamicDependencyOnSomeMetadatasThenOnlyRecalculatedWhenThoseMetadatasAreModified()
throws Exception {
schemas.modify(new MetadataSchemaTypesAlteration() {
@Override
public void alter(MetadataSchemaTypesBuilder types) {
types.getSchema(zeSchema.code()).create(calculatedMetadata).setType(STRING)
.defineDataEntry().asCalculated(CalculatorDependentOfSomeMetadatas.class);
}
});
Record record = new TestRecord(zeSchema)
.set(zeSchema.stringMetadata(), "toto");
recordServices.add(record);
assertThat(recalculationCounter.get()).isEqualTo(1);
assertThat(record.get(zeSchema.metadata(calculatedMetadata))).isEqualTo("toto,");
recordServices.update(record.set(zeSchema.anotherStringMetadata(), asList("edouard")));
assertThat(recalculationCounter.get()).isEqualTo(1);
assertThat(record.get(zeSchema.metadata(calculatedMetadata))).isEqualTo("toto,");
recordServices.update(record.set(zeSchema.stringMetadata(), "test"));
assertThat(recalculationCounter.get()).isEqualTo(2);
assertThat(record.get(zeSchema.metadata(calculatedMetadata))).isEqualTo("test,");
recordServices.update(record.set(zeSchema.dateTimeMetadata(), aDateTime));
assertThat(recalculationCounter.get()).isEqualTo(2);
assertThat(record.get(zeSchema.metadata(calculatedMetadata))).isEqualTo("test,");
recordServices.update(record.set(zeSchema.booleanMetadata(), true));
assertThat(recalculationCounter.get()).isEqualTo(3);
assertThat(record.get(zeSchema.metadata(calculatedMetadata))).isEqualTo("test,true");
recordServices.update(record.set(zeSchema.referenceMetadata(), anotherSchemaRecordId));
assertThat(recalculationCounter.get()).isEqualTo(3);
assertThat(record.get(zeSchema.metadata(calculatedMetadata))).isEqualTo("test,true");
recordServices.update(record.set(zeSchema.booleanMetadata(), false));
assertThat(recalculationCounter.get()).isEqualTo(4);
assertThat(record.get(zeSchema.metadata(calculatedMetadata))).isEqualTo("test,false");
}
@Test
public void givenACalculatorTryToObtainAMetadataWhichIsNotIncludedInADynamicDependencyThenException()
throws Exception {
schemas.modify(new MetadataSchemaTypesAlteration() {
@Override
public void alter(MetadataSchemaTypesBuilder types) {
types.getSchema(zeSchema.code()).create(calculatedMetadata).setType(STRING)
.defineDataEntry().asCalculated(BadCalculator.class);
}
});
Record record = new TestRecord(zeSchema)
.set(zeSchema.stringMetadata(), "toto");
try {
recordServices.add(record);
fail("Exception expected");
} catch (RecordServicesRuntimeException_ExceptionWhileCalculating e) {
assertThat(e)
.hasRootCauseExactlyInstanceOf(RecordServicesRuntimeException_CalculatorIsUsingAnForbiddenMetadata.class);
}
}
@Test
public void givenMetadataCalculatorHasADynamicDependencyOnAllMetadatasThenAlwaysRecalculated()
throws Exception {
schemas.modify(new MetadataSchemaTypesAlteration() {
@Override
public void alter(MetadataSchemaTypesBuilder types) {
types.getSchema(zeSchema.code()).create(calculatedMetadata).setType(STRING)
.defineDataEntry().asCalculated(CalculatorDependentOfEveryMetadatas.class);
}
});
Record record = new TestRecord(zeSchema)
.set(zeSchema.stringMetadata(), "toto");
recordServices.add(record);
assertThat(recalculationCounter.get()).isEqualTo(1);
assertThat(record.get(zeSchema.metadata(calculatedMetadata)))
.isEqualTo("toto,[],,,,");
recordServices.update(record.set(zeSchema.anotherStringMetadata(), asList("edouard")));
assertThat(recalculationCounter.get()).isEqualTo(2);
assertThat(record.get(zeSchema.metadata(calculatedMetadata)))
.isEqualTo("toto,[edouard],,,,");
recordServices.update(record.set(zeSchema.dateMetadata(), aDate));
assertThat(recalculationCounter.get()).isEqualTo(3);
assertThat(record.get(zeSchema.metadata(calculatedMetadata)))
.isEqualTo("toto,[edouard],2016-11-04,,,");
recordServices.update(record.set(zeSchema.dateTimeMetadata(), aDateTime));
assertThat(recalculationCounter.get()).isEqualTo(4);
assertThat(record.get(zeSchema.metadata(calculatedMetadata)))
.isEqualTo("toto,[edouard],2016-11-04,2016-11-04T01:02:03.000,,");
recordServices.update(record.set(zeSchema.booleanMetadata(), true));
assertThat(recalculationCounter.get()).isEqualTo(5);
assertThat(record.get(zeSchema.metadata(calculatedMetadata)))
.isEqualTo("toto,[edouard],2016-11-04,2016-11-04T01:02:03.000,true,");
recordServices.update(record.set(zeSchema.referenceMetadata(), anotherSchemaRecordId));
assertThat(recalculationCounter.get()).isEqualTo(6);
assertThat(record.get(zeSchema.metadata(calculatedMetadata)))
.isEqualTo("toto,[edouard],2016-11-04,2016-11-04T01:02:03.000,true,42");
}
@Test
public void givenMetadataCalculatorReturningAllAvailableMetadatasThenReturnAllAvailableEvenIfNullValue()
throws Exception {
schemas.modify(new MetadataSchemaTypesAlteration() {
@Override
public void alter(MetadataSchemaTypesBuilder types) {
types.getSchema(zeSchema.code()).create(calculatedMetadata).setType(STRING)
.defineDataEntry().asCalculated(CalculatorWhichReturnListOfAllAvailableMetadataLocalCodes.class);
}
});
Record record = new TestRecord(zeSchema)
.set(zeSchema.stringMetadata(), "toto");
recordServices.add(record);
assertThat(record.get(zeSchema.metadata(calculatedMetadata)))
.isEqualTo(
"anotherStringMetadata,booleanMetadata,dateMetadata,dateTimeMetadata,referenceMetadata,stringMetadata");
}
@Test
public void givenMetadataCalculatorReturningAllAvailableNonEmptyMetadatasThenReturnAllAvailableNonEmpty()
throws Exception {
schemas.modify(new MetadataSchemaTypesAlteration() {
@Override
public void alter(MetadataSchemaTypesBuilder types) {
types.getSchema(zeSchema.code()).create(calculatedMetadata).setType(STRING)
.defineDataEntry().asCalculated(CalculatorWhichReturnListOfAllAvailableMetadataWithValueLocalCodes.class);
}
});
Record record = new TestRecord(zeSchema)
.set(zeSchema.stringMetadata(), "toto");
recordServices.add(record);
assertThat(record.get(zeSchema.metadata(calculatedMetadata)))
.isEqualTo("stringMetadata");
recordServices.add(record
.set(zeSchema.anotherStringMetadata(), asList("aValue"))
.set(zeSchema.booleanMetadata(), true));
assertThat(record.get(zeSchema.metadata(calculatedMetadata)))
.isEqualTo("anotherStringMetadata,booleanMetadata,stringMetadata");
}
@Test(expected = MetadataSchemaBuilderRuntimeException.CyclicDependenciesInMetadata.class)
public void whenConfiguringTwoCalculatedMetadataDynamicallyDependingOnEachOtherThenFails()
throws Exception {
schemas.modify(new MetadataSchemaTypesAlteration() {
@Override
public void alter(MetadataSchemaTypesBuilder types) {
types.getSchema(zeSchema.code()).create(calculatedMetadata).setType(STRING)
.defineDataEntry().asCalculated(CalculatorDependentOfEveryMetadatas.class);
types.getSchema(zeSchema.code()).create(anotherCalculatedMetadata).setType(STRING)
.defineDataEntry().asCalculated(CalculatorDependentOfEveryMetadatas.class);
}
});
}
@Test
public void givenFiveCalculatorDependingOnEachOthersWithoutCyclicDependencyThenCalculatedCorrectly()
throws Exception {
schemas.modify(new MetadataSchemaTypesAlteration() {
@Override
public void alter(MetadataSchemaTypesBuilder types) {
types.getSchema(zeSchema.code()).create("calculated1").setType(NUMBER)
.defineDataEntry().asCalculated(Metadata1CalculatorDependingOn2_3_4.class);
types.getSchema(zeSchema.code()).create("calculated2").setType(NUMBER)
.defineDataEntry().asCalculated(Metadata2CalculatorDependingOnD_5.class);
types.getSchema(zeSchema.code()).create("calculated3").setType(NUMBER)
.defineDataEntry().asCalculated(Metadata3CalculatorDependingOn2_4.class);
types.getSchema(zeSchema.code()).create("calculated4").setType(NUMBER)
.defineDataEntry().asCalculated(Metadata4CalculatorDependingOnA_5.class);
types.getSchema(zeSchema.code()).create("calculated5").setType(NUMBER)
.defineDataEntry().asCalculated(Metadata5CalculatorDependingOnB_C.class);
types.getSchema(zeSchema.code()).create("metadataA").setType(NUMBER);
types.getSchema(zeSchema.code()).create("metadataB").setType(NUMBER);
types.getSchema(zeSchema.code()).create("metadataC").setType(NUMBER);
types.getSchema(zeSchema.code()).create("metadataD").setType(NUMBER);
}
});
Record record = new TestRecord(zeSchema);
record.set(zeSchema.metadata("metadataA"), 1);
record.set(zeSchema.metadata("metadataB"), 4);
record.set(zeSchema.metadata("metadataC"), 6);
record.set(zeSchema.metadata("metadataD"), 100);
recordServices.add(record);
assertThat(record.get(zeSchema.metadata("calculated1"))).isEqualTo(242.0);
assertThat(record.get(zeSchema.metadata("calculated2"))).isEqualTo(110.0);
assertThat(record.get(zeSchema.metadata("calculated3"))).isEqualTo(121.0);
assertThat(record.get(zeSchema.metadata("calculated4"))).isEqualTo(11.0);
assertThat(record.get(zeSchema.metadata("calculated5"))).isEqualTo(10.0);
}
@Test(expected = MetadataSchemaBuilderRuntimeException.CyclicDependenciesInMetadata.class)
public void givenFiveDynamicCalculatorDependingOnEachOthersWithCyclicDependencyThenCalculatedCorrectly()
throws Exception {
schemas.modify(new MetadataSchemaTypesAlteration() {
@Override
public void alter(MetadataSchemaTypesBuilder types) {
types.getSchema(zeSchema.code()).create("calculated1").setType(NUMBER)
.defineDataEntry().asJexlScript("calculated2+calculated3+calculated4");
types.getSchema(zeSchema.code()).create("calculated2").setType(NUMBER)
.defineDataEntry().asJexlScript("metadataD+calculated5");
types.getSchema(zeSchema.code()).create("calculated3").setType(NUMBER)
.defineDataEntry().asJexlScript("calculated2+calculated4");
types.getSchema(zeSchema.code()).create("calculated4").setType(NUMBER)
.defineDataEntry().asJexlScript("metadataA+calculated5");
types.getSchema(zeSchema.code()).create("calculated5").setType(NUMBER)
.defineDataEntry().asJexlScript("metadataB+metadataC+calculated1");
types.getSchema(zeSchema.code()).create("metadataA").setType(NUMBER);
types.getSchema(zeSchema.code()).create("metadataB").setType(NUMBER);
types.getSchema(zeSchema.code()).create("metadataC").setType(NUMBER);
types.getSchema(zeSchema.code()).create("metadataD").setType(NUMBER);
}
});
}
@Test
public void givenFiveDynamicCalculatorDependingOnEachOthersWithoutCyclicDependencyThenCalculatedCorrectly()
throws Exception {
schemas.modify(new MetadataSchemaTypesAlteration() {
@Override
public void alter(MetadataSchemaTypesBuilder types) {
types.getSchema(zeSchema.code()).create("calculated1").setType(NUMBER)
.defineDataEntry().asJexlScript("calculated2+calculated3+calculated4");
types.getSchema(zeSchema.code()).create("calculated2").setType(NUMBER)
.defineDataEntry().asJexlScript("metadataD+calculated5");
types.getSchema(zeSchema.code()).create("calculated3").setType(NUMBER)
.defineDataEntry().asJexlScript("calculated2+calculated4");
types.getSchema(zeSchema.code()).create("calculated4").setType(NUMBER)
.defineDataEntry().asJexlScript("metadataA+calculated5");
types.getSchema(zeSchema.code()).create("calculated5").setType(NUMBER)
.defineDataEntry().asJexlScript("metadataB+metadataC");
types.getSchema(zeSchema.code()).create("metadataA").setType(NUMBER);
types.getSchema(zeSchema.code()).create("metadataB").setType(NUMBER);
types.getSchema(zeSchema.code()).create("metadataC").setType(NUMBER);
types.getSchema(zeSchema.code()).create("metadataD").setType(NUMBER);
}
});
Record record = new TestRecord(zeSchema);
record.set(zeSchema.metadata("metadataA"), 1);
record.set(zeSchema.metadata("metadataB"), 4);
record.set(zeSchema.metadata("metadataC"), 6);
record.set(zeSchema.metadata("metadataD"), 100);
recordServices.add(record);
assertThat(record.get(zeSchema.metadata("calculated1"))).isEqualTo(242.0);
assertThat(record.get(zeSchema.metadata("calculated2"))).isEqualTo(110.0);
assertThat(record.get(zeSchema.metadata("calculated3"))).isEqualTo(121.0);
assertThat(record.get(zeSchema.metadata("calculated4"))).isEqualTo(11.0);
assertThat(record.get(zeSchema.metadata("calculated5"))).isEqualTo(10.0);
}
public static final class CalculatorDependentOfEveryMetadatas implements MetadataValueCalculator<String> {
DynamicLocalDependency dynamicLocalDependency = new DynamicLocalDependency() {
@Override
public boolean isDependentOf(Metadata metadata) {
return true;
}
};
@Override
public String calculate(CalculatorParameters parameters) {
DynamicDependencyValues values = parameters.get(dynamicLocalDependency);
String stringMetadataValue = values.getValue(zeSchema.stringMetadata().getLocalCode());
List<String> anotherStringMetadataValue = values.getValue(zeSchema.anotherStringMetadata().getLocalCode());
LocalDate dateMetadataValue = values.getValue(zeSchema.dateMetadata().getLocalCode());
LocalDateTime dateTimeMetadataValue = values.getValue(zeSchema.dateTimeMetadata().getLocalCode());
Boolean booleanMetadataValue = values.getValue(zeSchema.booleanMetadata().getLocalCode());
String referenceMetadataValue = values.getValue(zeSchema.referenceMetadata().getLocalCode());
recalculationCounter.incrementAndGet();
return StringUtils.join(new Object[] { stringMetadataValue, anotherStringMetadataValue, dateMetadataValue,
dateTimeMetadataValue, booleanMetadataValue, referenceMetadataValue }, ",");
}
@Override
public String getDefaultValue() {
return null;
}
@Override
public MetadataValueType getReturnType() {
return MetadataValueType.STRING;
}
@Override
public boolean isMultiValue() {
return false;
}
@Override
public List<? extends Dependency> getDependencies() {
return asList(dynamicLocalDependency);
}
}
public static final class CalculatorDependentOfSomeMetadatas implements MetadataValueCalculator<String> {
DynamicLocalDependency dynamicLocalDependency = new DynamicLocalDependency() {
@Override
public boolean isDependentOf(Metadata metadata) {
return metadata.getLocalCode().equals(zeSchema.stringMetadata().getLocalCode())
|| metadata.getLocalCode().equals(zeSchema.booleanMetadata().getLocalCode());
}
};
@Override
public String calculate(CalculatorParameters parameters) {
DynamicDependencyValues values = parameters.get(dynamicLocalDependency);
String stringMetadataValue = values.getValue(zeSchema.stringMetadata().getLocalCode());
Boolean booleanMetadataValue = values.getValue(zeSchema.booleanMetadata().getLocalCode());
recalculationCounter.incrementAndGet();
return StringUtils.join(new Object[] { stringMetadataValue, booleanMetadataValue }, ",");
}
@Override
public String getDefaultValue() {
return null;
}
@Override
public MetadataValueType getReturnType() {
return MetadataValueType.STRING;
}
@Override
public boolean isMultiValue() {
return false;
}
@Override
public List<? extends Dependency> getDependencies() {
return asList(dynamicLocalDependency);
}
}
public static final class BadCalculator implements MetadataValueCalculator<String> {
DynamicLocalDependency dynamicLocalDependency = new DynamicLocalDependency() {
@Override
public boolean isDependentOf(Metadata metadata) {
return metadata.getLocalCode().equals(zeSchema.stringMetadata().getLocalCode());
}
};
@Override
public String calculate(CalculatorParameters parameters) {
DynamicDependencyValues values = parameters.get(dynamicLocalDependency);
String stringMetadataValue = values.getValue(zeSchema.stringMetadata().getLocalCode());
Boolean booleanMetadataValue = values.getValue(zeSchema.booleanMetadata().getLocalCode());
return StringUtils.join(new Object[] { stringMetadataValue, booleanMetadataValue }, ",");
}
@Override
public String getDefaultValue() {
return null;
}
@Override
public MetadataValueType getReturnType() {
return MetadataValueType.STRING;
}
@Override
public boolean isMultiValue() {
return false;
}
@Override
public List<? extends Dependency> getDependencies() {
return asList(dynamicLocalDependency);
}
}
public static final class CalculatorWhichReturnListOfAllAvailableMetadataLocalCodes
implements MetadataValueCalculator<String> {
DynamicLocalDependency dynamicLocalDependency = new DynamicLocalDependency() {
@Override
public boolean isDependentOf(Metadata metadata) {
return true;
}
};
@Override
public String calculate(CalculatorParameters parameters) {
DynamicDependencyValues values = parameters.get(dynamicLocalDependency);
MetadataList allMetadatas = values.getAvailableMetadatas();
List<String> codes = new ArrayList<>(allMetadatas.toLocalCodesList());
Collections.sort(codes);
return StringUtils.join(codes, ",");
}
@Override
public String getDefaultValue() {
return null;
}
@Override
public MetadataValueType getReturnType() {
return MetadataValueType.STRING;
}
@Override
public boolean isMultiValue() {
return false;
}
@Override
public List<? extends Dependency> getDependencies() {
return asList(dynamicLocalDependency);
}
}
public static final class CalculatorWhichReturnListOfAllAvailableMetadataWithValueLocalCodes
implements MetadataValueCalculator<String> {
DynamicLocalDependency dynamicLocalDependency = new DynamicLocalDependency() {
@Override
public boolean isDependentOf(Metadata metadata) {
return true;
}
};
@Override
public String calculate(CalculatorParameters parameters) {
DynamicDependencyValues values = parameters.get(dynamicLocalDependency);
MetadataList allMetadatas = values.getAvailableMetadatasWithAValue();
List<String> codes = new ArrayList<>(allMetadatas.toLocalCodesList());
Collections.sort(codes);
return StringUtils.join(codes, ",");
}
@Override
public String getDefaultValue() {
return null;
}
@Override
public MetadataValueType getReturnType() {
return MetadataValueType.STRING;
}
@Override
public boolean isMultiValue() {
return false;
}
@Override
public List<? extends Dependency> getDependencies() {
return asList(dynamicLocalDependency);
}
}
public static final class Metadata4CalculatorDependingOnA_5 extends AbstractCalculatorSumOfDependencies
implements MetadataValueCalculator<Double> {
public Metadata4CalculatorDependingOnA_5() {
dynamicLocalDependency = new DynamicLocalDependency() {
@Override
public boolean isDependentOf(Metadata metadata) {
return asList("metadataA", "calculated5").contains(metadata.getLocalCode());
}
};
}
}
public static final class Metadata2CalculatorDependingOnD_5 extends AbstractCalculatorSumOfDependencies
implements MetadataValueCalculator<Double> {
public Metadata2CalculatorDependingOnD_5() {
dynamicLocalDependency = new DynamicLocalDependency() {
@Override
public boolean isDependentOf(Metadata metadata) {
return asList("metadataD", "calculated5").contains(metadata.getLocalCode());
}
};
}
}
public static final class Metadata3CalculatorDependingOn2_4 extends AbstractCalculatorSumOfDependencies
implements MetadataValueCalculator<Double> {
public Metadata3CalculatorDependingOn2_4() {
dynamicLocalDependency = new DynamicLocalDependency() {
@Override
public boolean isDependentOf(Metadata metadata) {
return asList("calculated2", "calculated4").contains(metadata.getLocalCode());
}
};
}
}
public static final class Metadata1CalculatorDependingOn2_3_4 extends AbstractCalculatorSumOfDependencies
implements MetadataValueCalculator<Double> {
public Metadata1CalculatorDependingOn2_3_4() {
dynamicLocalDependency = new DynamicLocalDependency() {
@Override
public boolean isDependentOf(Metadata metadata) {
return asList("calculated2", "calculated3", "calculated4").contains(metadata.getLocalCode());
}
};
}
}
public static final class Metadata5CalculatorDependingOnB_C extends AbstractCalculatorSumOfDependencies
implements MetadataValueCalculator<Double> {
public Metadata5CalculatorDependingOnB_C() {
dynamicLocalDependency = new DynamicLocalDependency() {
@Override
public boolean isDependentOf(Metadata metadata) {
return asList("metadataB", "metadataC").contains(metadata.getLocalCode());
}
};
}
}
public static abstract class AbstractCalculatorSumOfDependencies
implements MetadataValueCalculator<Double> {
protected DynamicLocalDependency dynamicLocalDependency;
@Override
public Double calculate(CalculatorParameters parameters) {
DynamicDependencyValues values = parameters.get(dynamicLocalDependency);
MetadataList allMetadatas = values.getAvailableMetadatasWithAValue();
double sum = 0;
for (Metadata metadata : allMetadatas) {
double value = values.getValue(metadata);
sum += value;
}
return sum;
}
@Override
public Double getDefaultValue() {
return null;
}
@Override
public MetadataValueType getReturnType() {
return MetadataValueType.NUMBER;
}
@Override
public boolean isMultiValue() {
return false;
}
@Override
public List<? extends Dependency> getDependencies() {
return asList(dynamicLocalDependency);
}
}
}