Avoid potentially dangerous divide operation
FEA: ItEr67S04BugFixing
This commit is contained in:
parent
0f174fb6ab
commit
dad38c8d6c
4 changed files with 109 additions and 64 deletions
|
|
@ -21,6 +21,7 @@
|
|||
package org.navalplanner.business.orders.daos;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -342,7 +343,8 @@ public class OrderElementDAO extends IntegrationEntityDAO<OrderElement>
|
|||
private BigDecimal average(BigDecimal divisor, BigDecimal sum) {
|
||||
BigDecimal average = new BigDecimal(0);
|
||||
if (sum.compareTo(new BigDecimal(0)) > 0) {
|
||||
average = sum.divide(divisor, RoundingMode.HALF_UP);
|
||||
average = sum.divide(divisor, new MathContext(2,
|
||||
RoundingMode.HALF_UP));
|
||||
}
|
||||
return average;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
package org.navalplanner.business.planner.entities;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.List;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
|
|
@ -79,8 +81,9 @@ public class HoursCostCalculator implements ICostCalculator {
|
|||
if(((filterStartDate == null) || day.compareTo(filterStartDate) >= 0) &&
|
||||
((filterEndDate == null) || day.compareTo(filterEndDate) <= 0)) {
|
||||
BigDecimal cost = advanceMeasurement.getValue().setScale(2)
|
||||
.multiply(new BigDecimal(totalHours)).divide(
|
||||
new BigDecimal(100));
|
||||
.multiply(new BigDecimal(totalHours))
|
||||
.divide(new BigDecimal(100),
|
||||
new MathContext(2, RoundingMode.HALF_UP));
|
||||
result.put(day, cost);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ import static org.navalplanner.business.BusinessGlobalNames.BUSINESS_SPRING_CONF
|
|||
import static org.navalplanner.business.test.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_TEST_FILE;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
|
@ -37,6 +39,10 @@ import java.util.UUID;
|
|||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hibernate.validator.ClassValidator;
|
||||
import org.hibernate.validator.InvalidValue;
|
||||
import org.joda.time.LocalDate;
|
||||
|
|
@ -88,6 +94,46 @@ public class OrderElementTest {
|
|||
defaultAdvanceTypesBootstrapListener.loadRequiredData();
|
||||
}
|
||||
|
||||
private Matcher<BigDecimal> sameValueAs(final BigDecimal value) {
|
||||
return new BaseMatcher<BigDecimal>() {
|
||||
|
||||
@Override
|
||||
public boolean matches(Object value) {
|
||||
if (value instanceof BigDecimal) {
|
||||
BigDecimal other = (BigDecimal) value;
|
||||
return ((BigDecimal) value).compareTo(other) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("must have the same value as " + value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class Division {
|
||||
private final MathContext mathContext;
|
||||
|
||||
private Division(MathContext mathContext) {
|
||||
Validate.notNull(mathContext);
|
||||
this.mathContext = mathContext;
|
||||
}
|
||||
|
||||
public BigDecimal divide(int dividend, int divisor) {
|
||||
return new BigDecimal(dividend).divide(new BigDecimal(divisor),
|
||||
mathContext);
|
||||
}
|
||||
}
|
||||
|
||||
private Division division(int numberOfDecimals) {
|
||||
return new Division(new MathContext(numberOfDecimals,
|
||||
RoundingMode.HALF_UP));
|
||||
}
|
||||
|
||||
private Division division = division(4);
|
||||
|
||||
private ClassValidator<OrderElement> orderElementValidator =
|
||||
new ClassValidator<OrderElement>(OrderElement.class);
|
||||
|
||||
|
|
@ -258,9 +304,8 @@ public class OrderElementTest {
|
|||
addAvanceAssignmentWithMeasurement(orderLine,
|
||||
givenAdvanceType("test2"), new BigDecimal(1000),
|
||||
new BigDecimal(600), false);
|
||||
|
||||
assertThat(orderLine.getAdvancePercentage(), equalTo(new BigDecimal(10)
|
||||
.setScale(4).divide(new BigDecimal(100))));
|
||||
assertThat(orderLine.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(10, 4)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -274,8 +319,8 @@ public class OrderElementTest {
|
|||
givenAdvanceType("test1"), new BigDecimal(2000),
|
||||
new BigDecimal(200), true, future);
|
||||
|
||||
assertThat(orderLine.getAdvancePercentage(), equalTo(new BigDecimal(10)
|
||||
.setScale(4).divide(new BigDecimal(100))));
|
||||
assertThat(orderLine.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(4, 100)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -292,8 +337,8 @@ public class OrderElementTest {
|
|||
PredefinedAdvancedTypes.PERCENTAGE.getType(), new BigDecimal(
|
||||
1000), new BigDecimal(600), true);
|
||||
|
||||
assertThat(orderLine.getAdvancePercentage(), equalTo(new BigDecimal(60)
|
||||
.setScale(4).divide(new BigDecimal(100))));
|
||||
assertThat(orderLine.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(60, 100)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -314,8 +359,8 @@ public class OrderElementTest {
|
|||
givenAdvanceType("test2"), new BigDecimal(1000),
|
||||
new BigDecimal(600), false);
|
||||
|
||||
assertThat(orderLine.getAdvancePercentage(), equalTo(new BigDecimal(20)
|
||||
.setScale(4).divide(new BigDecimal(100))));
|
||||
assertThat(orderLine.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(20, 100)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -347,9 +392,8 @@ public class OrderElementTest {
|
|||
indirectAdvanceAssignment.setReportGlobalAdvance(false);
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(orderElement.getAdvancePercentage(), equalTo(new BigDecimal(
|
||||
40).setScale(4).divide(new BigDecimal(100))));
|
||||
assertThat(orderElement.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(40, 100)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -381,9 +425,8 @@ public class OrderElementTest {
|
|||
indirectAdvanceAssignment.setReportGlobalAdvance(false);
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(orderElement.getAdvancePercentage(), equalTo(new BigDecimal(
|
||||
10).setScale(4).divide(new BigDecimal(100))));
|
||||
assertThat(orderElement.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(10, 100)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -404,9 +447,8 @@ public class OrderElementTest {
|
|||
10000), true, new BigDecimal(1), true, false);
|
||||
addAvanceAssignmentWithMeasurement(children.get(1), advanceType2,
|
||||
new BigDecimal(2000), new BigDecimal(200), true);
|
||||
|
||||
assertThat(orderElement.getAdvancePercentage(), equalTo(new BigDecimal(
|
||||
20).divide(new BigDecimal(100)).setScale(4)));
|
||||
assertThat(orderElement.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(20, 100)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -436,8 +478,8 @@ public class OrderElementTest {
|
|||
}
|
||||
}
|
||||
|
||||
assertThat(orderElement.getAdvancePercentage(), equalTo(new BigDecimal(
|
||||
20).setScale(4).divide(new BigDecimal(100))));
|
||||
assertThat(orderElement.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(20, 100)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -468,8 +510,8 @@ public class OrderElementTest {
|
|||
}
|
||||
}
|
||||
|
||||
assertThat(orderElement.getAdvancePercentage(), equalTo(new BigDecimal(
|
||||
22).divide(new BigDecimal(100)).setScale(4)));
|
||||
assertThat(orderElement.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(22, 100)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -494,8 +536,7 @@ public class OrderElementTest {
|
|||
100), new BigDecimal(90), true);
|
||||
|
||||
assertThat(orderLineGroup.getAdvancePercentage(),
|
||||
equalTo(new BigDecimal(90).setScale(4).divide(
|
||||
new BigDecimal(100))));
|
||||
sameValueAs(division.divide(90, 100)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -516,9 +557,8 @@ public class OrderElementTest {
|
|||
addAvanceAssignmentWithMeasurement(orderElement,
|
||||
PredefinedAdvancedTypes.PERCENTAGE.getType(), new BigDecimal(
|
||||
100), new BigDecimal(90), false);
|
||||
|
||||
assertThat(orderElement.getAdvancePercentage(), equalTo(new BigDecimal(
|
||||
20).divide(new BigDecimal(100)).setScale(4)));
|
||||
assertThat(orderElement.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(20, 100)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -546,8 +586,8 @@ public class OrderElementTest {
|
|||
new BigDecimal(1000), two, new BigDecimal(100), three,
|
||||
new BigDecimal(350), four, new BigDecimal(400));
|
||||
|
||||
assertThat(orderElement.getAdvancePercentage(), equalTo(new BigDecimal(
|
||||
4333).divide(new BigDecimal(10000)).setScale(4)));
|
||||
assertThat(orderElement.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(4333, 10000)));
|
||||
|
||||
Set<DirectAdvanceAssignment> directAdvanceAssignments = orderElement
|
||||
.getDirectAdvanceAssignments();
|
||||
|
|
@ -700,9 +740,8 @@ public class OrderElementTest {
|
|||
addAvanceAssignmentWithMeasurements(children.get(1), advanceType2,
|
||||
true, new BigDecimal(1000), two, new BigDecimal(100), three,
|
||||
new BigDecimal(350), four, new BigDecimal(400));
|
||||
|
||||
assertThat(orderElement.getAdvancePercentage(), equalTo(new BigDecimal(
|
||||
4333).divide(new BigDecimal(10000)).setScale(4)));
|
||||
assertThat(orderElement.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(4333, 10000)));
|
||||
|
||||
Set<DirectAdvanceAssignment> directAdvanceAssignments = orderElement
|
||||
.getDirectAdvanceAssignments();
|
||||
|
|
@ -736,18 +775,16 @@ public class OrderElementTest {
|
|||
|
||||
AdvanceMeasurement next = iterator.next();
|
||||
assertThat(next.getDate(), equalTo(one));
|
||||
assertThat(next.getValue(), equalTo(new BigDecimal(66600).setScale(4)
|
||||
.divide(new BigDecimal(10000))));
|
||||
|
||||
assertThat(next.getValue(), sameValueAs(division.divide(66600, 10000)));
|
||||
|
||||
next = iterator.next();
|
||||
assertThat(next.getDate(), equalTo(two));
|
||||
assertThat(next.getValue(), equalTo(new BigDecimal(133300).setScale(4)
|
||||
.divide(new BigDecimal(10000))));
|
||||
assertThat(next.getValue(), sameValueAs(division.divide(133300, 10000)));
|
||||
|
||||
next = iterator.next();
|
||||
assertThat(next.getDate(), equalTo(three));
|
||||
assertThat(next.getValue(), equalTo(new BigDecimal(366600).setScale(4)
|
||||
.divide(new BigDecimal(10000))));
|
||||
assertThat(next.getValue(), sameValueAs(division.divide(366600, 10000)));
|
||||
|
||||
next = iterator.next();
|
||||
assertThat(next.getDate(), equalTo(four));
|
||||
|
|
@ -755,8 +792,7 @@ public class OrderElementTest {
|
|||
|
||||
next = iterator.next();
|
||||
assertThat(next.getDate(), equalTo(five));
|
||||
assertThat(next.getValue(), equalTo(new BigDecimal(4333).setScale(4)
|
||||
.divide(new BigDecimal(100))));
|
||||
assertThat(next.getValue(), sameValueAs(division.divide(4333, 100)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -794,9 +830,9 @@ public class OrderElementTest {
|
|||
equalTo(0));
|
||||
assertThat(orderLineGroup_1.getIndirectAdvanceAssignments().size(),
|
||||
equalTo(3));
|
||||
|
||||
assertThat(orderLineGroup_1.getAdvancePercentage(),
|
||||
equalTo(new BigDecimal(50).setScale(4).divide(
|
||||
new BigDecimal(100))));
|
||||
sameValueAs(division.divide(50, 100)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -831,9 +867,9 @@ public class OrderElementTest {
|
|||
equalTo(0));
|
||||
assertThat(orderLineGroup_1.getIndirectAdvanceAssignments().size(),
|
||||
equalTo(3));
|
||||
|
||||
assertThat(orderLineGroup_1.getAdvancePercentage(),
|
||||
equalTo(new BigDecimal(20).setScale(4).divide(
|
||||
new BigDecimal(100))));
|
||||
sameValueAs(division.divide(20, 100)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -852,8 +888,8 @@ public class OrderElementTest {
|
|||
addAvanceAssignmentWithMeasurement(children.get(1), advanceType,
|
||||
new BigDecimal(100), new BigDecimal(20), true);
|
||||
|
||||
assertThat(orderElement.getAdvancePercentage(), equalTo(new BigDecimal(
|
||||
2666).divide(new BigDecimal(10000)).setScale(4)));
|
||||
assertThat(orderElement.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(2666, 10000)));
|
||||
|
||||
Set<IndirectAdvanceAssignment> indirectAdvanceAssignments = ((OrderLineGroup) orderElement)
|
||||
.getIndirectAdvanceAssignments();
|
||||
|
|
@ -865,9 +901,8 @@ public class OrderElementTest {
|
|||
indirectAdvanceAssignment.setReportGlobalAdvance(false);
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(orderElement.getAdvancePercentage(), equalTo(new BigDecimal(
|
||||
26).setScale(4).divide(new BigDecimal(100))));
|
||||
assertThat(orderElement.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(26, 4)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -895,8 +930,8 @@ public class OrderElementTest {
|
|||
new BigDecimal(100), one, new BigDecimal(10), four,
|
||||
new BigDecimal(20), five, new BigDecimal(50));
|
||||
|
||||
assertThat(orderElement.getAdvancePercentage(), equalTo(new BigDecimal(
|
||||
4666).setScale(4).divide(new BigDecimal(10000))));
|
||||
assertThat(orderElement.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(4666, 10000)));
|
||||
|
||||
Set<DirectAdvanceAssignment> directAdvanceAssignments = orderElement
|
||||
.getDirectAdvanceAssignments();
|
||||
|
|
@ -974,8 +1009,8 @@ public class OrderElementTest {
|
|||
new BigDecimal(10000), one, new BigDecimal(100), two,
|
||||
new BigDecimal(1000), three, new BigDecimal(5000));
|
||||
|
||||
assertThat(orderElement.getAdvancePercentage(), equalTo(new BigDecimal(
|
||||
833).divide(new BigDecimal(10000)).setScale(4)));
|
||||
assertThat(orderElement.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(833, 10000)));
|
||||
|
||||
Set<IndirectAdvanceAssignment> indirectAdvanceAssignments = ((OrderLineGroup) orderElement)
|
||||
.getIndirectAdvanceAssignments();
|
||||
|
|
@ -995,9 +1030,9 @@ public class OrderElementTest {
|
|||
equalTo(3));
|
||||
assertThat(advanceAssignment.getLastAdvanceMeasurement().getValue(),
|
||||
equalTo(new BigDecimal(5000)));
|
||||
|
||||
assertThat(advanceAssignment.getAdvancePercentage(),
|
||||
equalTo(new BigDecimal(4545).divide(new BigDecimal(10000))
|
||||
.setScale(4)));
|
||||
sameValueAs(division.divide(4545, 10000)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -1021,8 +1056,8 @@ public class OrderElementTest {
|
|||
addAvanceAssignmentWithoutMeasurement(children.get(1), advanceType,
|
||||
new BigDecimal(1000), true);
|
||||
|
||||
assertThat(orderElement.getAdvancePercentage(), equalTo(new BigDecimal(
|
||||
833).divide(new BigDecimal(10000)).setScale(4)));
|
||||
assertThat(orderElement.getAdvancePercentage(),
|
||||
sameValueAs(division.divide(833, 10000)));
|
||||
|
||||
Set<IndirectAdvanceAssignment> indirectAdvanceAssignments = ((OrderLineGroup) orderElement)
|
||||
.getIndirectAdvanceAssignments();
|
||||
|
|
@ -1042,9 +1077,9 @@ public class OrderElementTest {
|
|||
equalTo(3));
|
||||
assertThat(advanceAssignment.getLastAdvanceMeasurement().getValue(),
|
||||
equalTo(new BigDecimal(5000)));
|
||||
|
||||
assertThat(advanceAssignment.getAdvancePercentage(),
|
||||
equalTo(new BigDecimal(4545).divide(new BigDecimal(10000))
|
||||
.setScale(4)));
|
||||
sameValueAs(division.divide(4545, 10000)));
|
||||
}
|
||||
|
||||
public static void removeReportGlobalAdvanceFromChildrenAdvance(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package org.navalplanner.web.montecarlo;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.joda.time.Days;
|
||||
|
|
@ -175,9 +177,12 @@ public class MonteCarloTask {
|
|||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
private static final MathContext mathContext = new MathContext(2,
|
||||
RoundingMode.HALF_UP);
|
||||
|
||||
public BigDecimal getPessimisticDurationPercentageUpperLimit() {
|
||||
return BigDecimal.valueOf(pessimisticDurationPercentage).divide(
|
||||
BigDecimal.valueOf(100));
|
||||
BigDecimal.valueOf(100), mathContext);
|
||||
}
|
||||
|
||||
public BigDecimal getNormalDurationPercentageLowerLimit() {
|
||||
|
|
@ -187,7 +192,7 @@ public class MonteCarloTask {
|
|||
public BigDecimal getNormalDurationPercentageUpperLimit() {
|
||||
BigDecimal result = BigDecimal.valueOf(pessimisticDurationPercentage
|
||||
+ normalDurationPercentage);
|
||||
return result.divide(BigDecimal.valueOf(100));
|
||||
return result.divide(BigDecimal.valueOf(100), mathContext);
|
||||
}
|
||||
|
||||
public BigDecimal getOptimisticDurationPercentageLowerLimit() {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue