Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.gst.portfolio.interestratechart.domain; import static com.gst.portfolio.interestratechart.InterestRateChartApiConstants.INTERESTRATE_CHART_RESOURCE_NAME; import static com.gst.portfolio.interestratechart.InterestRateChartApiConstants.deleteParamName; import static com.gst.portfolio.interestratechart.InterestRateChartApiConstants.descriptionParamName; import static com.gst.portfolio.interestratechart.InterestRateChartApiConstants.idParamName; import static com.gst.portfolio.interestratechart.InterestRateChartSlabApiConstants.amountRangeFromParamName; import static com.gst.portfolio.interestratechart.InterestRateChartSlabApiConstants.amountRangeToParamName; import static com.gst.portfolio.interestratechart.InterestRateChartSlabApiConstants.annualInterestRateParamName; import static com.gst.portfolio.interestratechart.InterestRateChartSlabApiConstants.fromPeriodParamName; import static com.gst.portfolio.interestratechart.InterestRateChartSlabApiConstants.periodTypeParamName; import static com.gst.portfolio.interestratechart.InterestRateChartSlabApiConstants.toPeriodParamName; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.OneToMany; import javax.persistence.Table; import com.gst.infrastructure.core.api.JsonCommand; import com.gst.infrastructure.core.data.ApiParameterError; import com.gst.infrastructure.core.data.DataValidatorBuilder; import com.gst.infrastructure.core.exception.PlatformApiDataValidationException; import com.gst.portfolio.interestratechart.InterestRateChartApiConstants; import com.gst.portfolio.interestratechart.InterestRateChartSlabApiConstants; import com.gst.portfolio.savings.SavingsPeriodFrequencyType; import org.joda.time.LocalDate; import com.gst.infrastructure.core.domain.AbstractPersistableCustom; import com.google.gson.JsonArray; import com.google.gson.JsonObject; @Entity @Table(name = "m_interest_rate_chart") public class InterestRateChart extends AbstractPersistableCustom<Long> { @Embedded private InterestRateChartFields chartFields; @OneToMany(mappedBy = "interestRateChart", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) private Set<InterestRateChartSlab> chartSlabs = new HashSet<>(); protected InterestRateChart() { // } public static InterestRateChart createNew(InterestRateChartFields chartFields, Collection<InterestRateChartSlab> interestRateChartSlabs) { return new InterestRateChart(chartFields, new HashSet<>(interestRateChartSlabs)); } private InterestRateChart(InterestRateChartFields chartFields, Set<InterestRateChartSlab> interestRateChartSlabs) { final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(INTERESTRATE_CHART_RESOURCE_NAME); this.chartFields = chartFields; // validate before setting the other fields this.validateChartSlabs(baseDataValidator); this.throwExceptionIfValidationWarningsExist(dataValidationErrors); this.addChartSlabs(interestRateChartSlabs); } public void validateChartSlabs(DataValidatorBuilder baseDataValidator) { Collection<InterestRateChartSlab> chartSlabs = this.setOfChartSlabs(); Integer tmpPeriodType = null; List<InterestRateChartSlab> chartSlabsList = new ArrayList<>(chartSlabs); boolean isPrimaryGroupingByAmount = this.chartFields.isPrimaryGroupingByAmount(); chartSlabsList.sort(new InterestRateChartSlabComparator<InterestRateChartSlab>(isPrimaryGroupingByAmount)); boolean isPeriodChart = !isPrimaryGroupingByAmount; boolean isAmountChart = isPrimaryGroupingByAmount; for (int i = 0; i < chartSlabsList.size(); i++) { InterestRateChartSlab iSlabs = chartSlabsList.get(i); if (!iSlabs.slabFields().isValidChart(isPrimaryGroupingByAmount)) { if (isPrimaryGroupingByAmount) { baseDataValidator.parameter(InterestRateChartSlabApiConstants.amountRangeFromParamName) .failWithCode("cannot.be.blank"); } else { baseDataValidator.parameter(InterestRateChartSlabApiConstants.fromPeriodParamName) .failWithCode("cannot.be.blank"); } } else if (i > 0) { if (isPeriodChart ^ iSlabs.slabFields().fromPeriod() != null) { baseDataValidator .failWithCodeNoParameterAddedToErrorCode("chart.slabs.period.range.incomplete"); isPeriodChart = isPeriodChart || iSlabs.slabFields().fromPeriod() != null; } if (isAmountChart ^ iSlabs.slabFields().getAmountRangeFrom() != null) { baseDataValidator .failWithCodeNoParameterAddedToErrorCode("chart.slabs.amount.range.incomplete"); isAmountChart = isAmountChart || iSlabs.slabFields().getAmountRangeFrom() != null; } } if (i == 0) { tmpPeriodType = iSlabs.slabFields().periodType(); if (iSlabs.slabFields().isNotProperChartStart()) { baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.range.start.incorrect", iSlabs.slabFields().fromPeriod(), iSlabs.slabFields().getAmountRangeFrom()); } isAmountChart = isAmountChart || iSlabs.slabFields().getAmountRangeFrom() != null; isPeriodChart = isPeriodChart || iSlabs.slabFields().fromPeriod() != null; } else if (iSlabs.slabFields().periodType() != null && !iSlabs.slabFields().periodType().equals(tmpPeriodType)) { baseDataValidator.parameter(periodTypeParamName).value(iSlabs.slabFields().periodType()) .failWithCode("period.type.is.not.same", tmpPeriodType); } if (i + 1 < chartSlabsList.size()) { InterestRateChartSlab nextSlabs = chartSlabsList.get(i + 1); if (iSlabs.slabFields().isValidChart(isPrimaryGroupingByAmount) && nextSlabs.slabFields().isValidChart(isPrimaryGroupingByAmount)) { if (iSlabs.slabFields().isRateChartOverlapping(nextSlabs.slabFields(), isPrimaryGroupingByAmount)) { baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.range.overlapping", iSlabs.slabFields().fromPeriod(), iSlabs.slabFields().toPeriod(), nextSlabs.slabFields().fromPeriod(), nextSlabs.slabFields().toPeriod(), iSlabs.slabFields().getAmountRangeFrom(), iSlabs.slabFields().getAmountRangeTo(), nextSlabs.slabFields().getAmountRangeFrom(), nextSlabs.slabFields().getAmountRangeTo()); } else if (iSlabs.slabFields().isRateChartHasGap(nextSlabs.slabFields(), isPrimaryGroupingByAmount)) { baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.range.has.gap", iSlabs.slabFields().fromPeriod(), iSlabs.slabFields().toPeriod(), nextSlabs.slabFields().fromPeriod(), nextSlabs.slabFields().toPeriod(), iSlabs.slabFields().getAmountRangeFrom(), iSlabs.slabFields().getAmountRangeTo(), nextSlabs.slabFields().getAmountRangeFrom(), nextSlabs.slabFields().getAmountRangeTo()); } if (isPrimaryGroupingByAmount) { if (!iSlabs.slabFields().isAmountSame(nextSlabs.slabFields())) { if (InterestRateChartSlabFields.isNotProperPeriodStart(nextSlabs.slabFields())) { baseDataValidator.failWithCodeNoParameterAddedToErrorCode( "chart.slabs.period.range.start.incorrect", nextSlabs.slabFields().toPeriod()); } if (iSlabs.slabFields().toPeriod() != null) { baseDataValidator.failWithCodeNoParameterAddedToErrorCode( "chart.slabs.period.range.end.incorrect", iSlabs.slabFields().toPeriod()); } } } else if (!iSlabs.slabFields().isPeriodsSame(nextSlabs.slabFields())) { if (InterestRateChartSlabFields.isNotProperAmountStart(nextSlabs.slabFields())) { baseDataValidator.failWithCodeNoParameterAddedToErrorCode( "chart.slabs.amount.range.start.incorrect", nextSlabs.slabFields().getAmountRangeFrom()); } if (iSlabs.slabFields().getAmountRangeTo() != null) { baseDataValidator.failWithCodeNoParameterAddedToErrorCode( "chart.slabs.amount.range.end.incorrect", iSlabs.slabFields().getAmountRangeTo()); } } } } else if (iSlabs.slabFields().isNotProperPriodEnd()) { baseDataValidator.failWithCodeNoParameterAddedToErrorCode("chart.slabs.range.end.incorrect", iSlabs.slabFields().toPeriod(), iSlabs.slabFields().getAmountRangeTo()); } } } public void addChartSlabs(Collection<InterestRateChartSlab> interestRateChartSlabsSet) { Set<InterestRateChartSlab> existingChartSlabs = setOfChartSlabs(); for (InterestRateChartSlab newChartSlabs : interestRateChartSlabsSet) { newChartSlabs.setInterestRateChart(this); existingChartSlabs.add(newChartSlabs); } } public void addChartSlab(InterestRateChartSlab newChartSlab) { newChartSlab.setInterestRateChart(this); setOfChartSlabs().add(newChartSlab); } public Set<InterestRateChartSlab> setOfChartSlabs() { if (this.chartSlabs == null) { this.chartSlabs = new HashSet<>(); } return this.chartSlabs; } public void update(JsonCommand command, final Map<String, Object> actualChanges) { final List<ApiParameterError> dataValidationErrors = new ArrayList<>(); final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors) .resource(INTERESTRATE_CHART_RESOURCE_NAME); this.update(command, actualChanges, baseDataValidator, null, null); throwExceptionIfValidationWarningsExist(dataValidationErrors); } public void update(JsonCommand command, final Map<String, Object> actualChanges, final DataValidatorBuilder baseDataValidator, final Set<InterestRateChart> existingCharts, String currencyCode) { this.chartFields.update(command, actualChanges, baseDataValidator); // interestRateChartSlabs if (command.hasParameter(InterestRateChartApiConstants.chartSlabs)) { updateChartSlabs(command, actualChanges, baseDataValidator, currencyCode); } this.validateCharts(baseDataValidator, existingCharts); } private void validateCharts(final DataValidatorBuilder baseDataValidator, final Set<InterestRateChart> existingCharts) { for (InterestRateChart existingChart : existingCharts) { if (!existingChart.equals(this)) { if (this.chartFields.isOverlapping(existingChart.chartFields)) { baseDataValidator.failWithCodeNoParameterAddedToErrorCode( "chart.overlapping.from.and.end.dates", existingChart.getFromDateAsLocalDate(), existingChart.getEndDateAsLocalDate(), this.getFromDateAsLocalDate(), this.getEndDateAsLocalDate()); } } } } public void updateChartSlabs(JsonCommand command, final Map<String, Object> actualChanges, final DataValidatorBuilder baseDataValidator, String currencyCode) { final Map<String, Object> deleteChartSlabs = new HashMap<>(); final Map<String, Object> chartSlabsChanges = new HashMap<>(); final Locale locale = command.extractLocale(); if (command.hasParameter(InterestRateChartApiConstants.chartSlabs)) { final JsonArray array = command.arrayOfParameterNamed(InterestRateChartApiConstants.chartSlabs); if (array != null) { for (int i = 0; i < array.size(); i++) { final JsonObject chartSlabsElement = array.get(i).getAsJsonObject(); JsonCommand chartSlabsCommand = JsonCommand.fromExistingCommand(command, chartSlabsElement); if (chartSlabsCommand.parameterExists(idParamName)) { final Long chartSlabId = chartSlabsCommand.longValueOfParameterNamed(idParamName); final InterestRateChartSlab chartSlab = this.findChartSlab(chartSlabId); if (chartSlab == null) { baseDataValidator.parameter(idParamName).value(chartSlabId) .failWithCode("no.chart.slab.associated.with.id"); } else if (chartSlabsCommand.parameterExists(deleteParamName)) { if (this.removeChartSlab(chartSlab)) { deleteChartSlabs.put(idParamName, chartSlabId); } } else { chartSlab.update(chartSlabsCommand, chartSlabsChanges, baseDataValidator, locale); } } else { /** * TODO: AA: Move this code to * InterestRateChartSlabAssembler */ final String description = chartSlabsCommand .stringValueOfParameterNamed(descriptionParamName); final Integer periodTypeId = chartSlabsCommand .integerValueOfParameterNamed(periodTypeParamName, locale); final SavingsPeriodFrequencyType periodFrequencyType = SavingsPeriodFrequencyType .fromInt(periodTypeId); final Integer fromPeriod = chartSlabsCommand .integerValueOfParameterNamed(fromPeriodParamName, locale); final Integer toPeriod = chartSlabsCommand.integerValueOfParameterNamed(toPeriodParamName, locale); final BigDecimal amountRangeFrom = chartSlabsCommand .bigDecimalValueOfParameterNamed(amountRangeFromParamName, locale); final BigDecimal amountRangeTo = chartSlabsCommand .bigDecimalValueOfParameterNamed(amountRangeToParamName, locale); final BigDecimal annualInterestRate = chartSlabsCommand .bigDecimalValueOfParameterNamed(annualInterestRateParamName, locale); final InterestRateChartSlabFields slabFields = InterestRateChartSlabFields.createNew( description, periodFrequencyType, fromPeriod, toPeriod, amountRangeFrom, amountRangeTo, annualInterestRate, currencyCode); final InterestRateChartSlab chartSlab = InterestRateChartSlab.createNew(slabFields, this); chartSlab.slabFields().validateChartSlabPlatformRules(chartSlabsCommand, baseDataValidator, locale); chartSlab.updateIncentives(chartSlabsCommand, actualChanges, baseDataValidator, chartSlab, locale); this.addChartSlab(chartSlab); } } } } // add chart slab changes to actual changes list. if (!chartSlabsChanges.isEmpty()) { actualChanges.put(InterestRateChartApiConstants.chartSlabs, chartSlabsChanges); } // add deleted chart Slabs to actual changes if (!deleteChartSlabs.isEmpty()) { actualChanges.put("deletedChartSlabs", deleteChartSlabs); } this.validateChartSlabs(baseDataValidator); } public InterestRateChartSlab findChartSlab(Long chartSlabId) { final Set<InterestRateChartSlab> chartSlabs = setOfChartSlabs(); for (InterestRateChartSlab interestRateChartSlab : chartSlabs) { if (interestRateChartSlab.getId().equals(chartSlabId)) { return interestRateChartSlab; } } return null; } private boolean removeChartSlab(InterestRateChartSlab chartSlab) { final Set<InterestRateChartSlab> chartSlabs = setOfChartSlabs(); return chartSlabs.remove(chartSlab); } public LocalDate getFromDateAsLocalDate() { return this.chartFields.getFromDateAsLocalDate(); } public LocalDate getEndDateAsLocalDate() { return this.chartFields.getEndDateAsLocalDate(); } private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) { if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); } } public InterestRateChartFields chartFields() { return this.chartFields; } public boolean isApplicableChartFor(final LocalDate target) { return this.chartFields.isApplicableChartFor(target); } }